diff --git a/sdk/core/azure_core/CHANGELOG.md b/sdk/core/azure_core/CHANGELOG.md index 6cf68347b9..b5c9bbe6b5 100644 --- a/sdk/core/azure_core/CHANGELOG.md +++ b/sdk/core/azure_core/CHANGELOG.md @@ -4,6 +4,7 @@ ### Features Added +- Added `ItemIterator::continuation_token()` and `with_continuation_token()` to resume paging items. The current page is restarted until _after_ all items have been iterated. - Added `Response::to_raw_response()` function to create a `RawResponse` from cloned data. - Added `UrlExt::append_path()`. - Implemented `IntoFuture` for a `Poller`. Call `await` on a Poller to get the final model, or `into_stream()` to get a `futures::Stream` to poll the operation manually. @@ -25,6 +26,8 @@ ### Bugs Fixed +- `ItemIterator::into_pages()` now properly supports resuming from the current page until _after_ all items have been iterated. + ### Other Changes ## 0.29.1 (2025-10-06) diff --git a/sdk/core/azure_core/src/http/pager.rs b/sdk/core/azure_core/src/http/pager.rs index 7b85a6244c..b352b38056 100644 --- a/sdk/core/azure_core/src/http/pager.rs +++ b/sdk/core/azure_core/src/http/pager.rs @@ -3,7 +3,10 @@ //! Types and methods for pageable responses. -use crate::http::{headers::HeaderName, response::Response, DeserializeWith, Format, JsonFormat}; +use crate::{ + error::ErrorKind, + http::{headers::HeaderName, response::Response, Context, DeserializeWith, Format, JsonFormat}, +}; use async_trait::async_trait; use futures::{stream::unfold, FutureExt, Stream}; use std::{ @@ -199,6 +202,13 @@ where /// ``` pub type Pager = ItemIterator>; +/// Options for configuring the behavior of a [`Pager`]. +#[derive(Clone, Debug, Default)] +pub struct PagerOptions<'a> { + /// Context for HTTP requests made by the [`Pager`]. + pub context: Context<'a>, +} + #[cfg(not(target_arch = "wasm32"))] type BoxedStream

= Box> + Send>; @@ -262,6 +272,8 @@ type BoxedStream

= Box>>; pub struct ItemIterator { #[pin] stream: Pin>, + continuation_token: Option, + next_token: Arc>>, current: Option, } @@ -270,7 +282,7 @@ impl ItemIterator

{ /// /// This method expect a callback that accepts a single [`PagerState`] parameter, and returns a [`PagerResult`] value asynchronously. /// The `C` type parameter is the type of the next link/continuation token. It may be any [`Send`]able type. - /// The result will be an asynchronous stream of [`Result`](typespec::Result) values. + /// The result will be an asynchronous stream of [`Result`](crate::Result) values. /// /// The first time your callback is called, it will be called with [`Option::None`], indicating no next link/continuation token is present. /// @@ -302,7 +314,7 @@ impl ItemIterator

{ /// } /// let url = "https://example.com/my_paginated_api".parse().unwrap(); /// let mut base_req = Request::new(url, Method::Get); - /// let pager = ItemIterator::from_callback(move |next_link: PagerState| { + /// let pager = ItemIterator::from_callback(move |next_link: PagerState, ctx| { /// // The callback must be 'static, so you have to clone and move any values you want to use. /// let pipeline = pipeline.clone(); /// let api_version = api_version.clone(); @@ -321,7 +333,7 @@ impl ItemIterator

{ /// .append_pair("api-version", &api_version); /// } /// let resp = pipeline - /// .send(&Context::new(), &mut req, None) + /// .send(&ctx, &mut req, None) /// .await?; /// let (status, headers, body) = resp.deconstruct(); /// let result: ListItemsResult = json::from_json(&body)?; @@ -334,7 +346,7 @@ impl ItemIterator

{ /// None => PagerResult::Done { response: resp } /// }) /// } - /// }); + /// }, None); /// ``` /// /// To page results using headers: @@ -357,7 +369,7 @@ impl ItemIterator

{ /// } /// let url = "https://example.com/my_paginated_api".parse().unwrap(); /// let mut base_req = Request::new(url, Method::Get); - /// let pager = ItemIterator::from_callback(move |continuation| { + /// let pager = ItemIterator::from_callback(move |continuation, ctx| { /// // The callback must be 'static, so you have to clone and move any values you want to use. /// let pipeline = pipeline.clone(); /// let mut req = base_req.clone(); @@ -366,25 +378,38 @@ impl ItemIterator

{ /// req.insert_header("x-ms-continuation", continuation); /// } /// let resp: Response = pipeline - /// .send(&Context::new(), &mut req, None) + /// .send(&ctx, &mut req, None) /// .await? /// .into(); /// Ok(PagerResult::from_response_header(resp, &HeaderName::from_static("x-next-continuation"))) /// } - /// }); + /// }, None); /// ``` pub fn from_callback< // This is a bit gnarly, but the only thing that differs between the WASM/non-WASM configs is the presence of Send bounds. - #[cfg(not(target_arch = "wasm32"))] C: AsRef + Send + 'static, - #[cfg(not(target_arch = "wasm32"))] F: Fn(PagerState) -> Fut + Send + 'static, + #[cfg(not(target_arch = "wasm32"))] C: AsRef + FromStr + Send + 'static, + #[cfg(not(target_arch = "wasm32"))] F: Fn(PagerState, Context<'static>) -> Fut + Send + 'static, #[cfg(not(target_arch = "wasm32"))] Fut: Future>> + Send + 'static, - #[cfg(target_arch = "wasm32")] C: AsRef + 'static, - #[cfg(target_arch = "wasm32")] F: Fn(PagerState) -> Fut + 'static, + #[cfg(target_arch = "wasm32")] C: AsRef + FromStr + 'static, + #[cfg(target_arch = "wasm32")] F: Fn(PagerState, Context<'static>) -> Fut + 'static, #[cfg(target_arch = "wasm32")] Fut: Future>> + 'static, >( make_request: F, - ) -> Self { - Self::from_stream(iter_from_callback(make_request, || None, |_| {})) + options: Option>, + ) -> Self + where + ::Err: std::error::Error, + { + let options = options.unwrap_or_default(); + let next_token = Arc::new(Mutex::new(None::)); + let stream = iter_from_callback(make_request, options.context.clone(), next_token.clone()); + + Self { + stream: Box::pin(stream), + continuation_token: None, + next_token, + current: None, + } } /// Creates a [`ItemIterator

`] from a raw stream of [`Result

`](crate::Result

) values. @@ -399,6 +424,8 @@ impl ItemIterator

{ ) -> Self { Self { stream: Box::pin(stream), + continuation_token: None, + next_token: Default::default(), current: None, } } @@ -408,12 +435,76 @@ impl ItemIterator

{ /// You can use this to asynchronously iterate pages returned by a collection request to a service. /// This allows you to get the individual pages' [`Response

`], from which you can iterate items in each page /// or deserialize the raw response as appropriate. + /// + /// The returned `PageIterator` resumes from the current page until _after_ all items are processed. + /// It does not continue on the next page until you call `next()` after the last item in the current page + /// because of how iterators are implemented. This may yield duplicates but will reduce the likelihood of skipping items instead. pub fn into_pages(self) -> PageIterator

{ + // Attempt to start paging from the current page so that we don't skip items, + // assuming the service collection hasn't changed (most services don't create ephemeral snapshots). + if let Ok(mut token) = self.next_token.lock() { + *token = self.continuation_token; + } + PageIterator { stream: self.stream, - continuation_token: Default::default(), + continuation_token: self.next_token, } } + + /// Start the `ItemIterator` at the page referenced by `continuation_token`. + /// + /// You should call this before iterating the [`Stream`] or results may be unpredictable. + /// Iteration of items will start from the beginning on the current page until _after_ all items are iterated. + /// It does not continue on the next page until you call `next()` after the last item in the current page + /// because of how iterators are implemented. This may yield duplicates but will reduce the likelihood of skipping items instead. + /// + /// # Examples + /// + /// Using a result of a call to [`ItemIterator::continuation_token`] in another process, you can create a new `ItemIterator` + /// that, when first iterated, will get the next page of results. + /// + /// ``` no_run + /// use azure_identity::DeveloperToolsCredential; + /// use azure_security_keyvault_secrets::SecretClient; + /// use futures::stream::TryStreamExt as _; + /// + /// # #[tokio::main] + /// # async fn main() -> azure_core::Result<()> { + /// let client = SecretClient::new("https://my-vault.vault.azure.net", DeveloperToolsCredential::new(None)?, None)?; + /// + /// // Start the first pager at the first page. + /// let mut pager = client.list_secret_properties(None)?; + /// + /// // Continue the second pager from where the first pager left off, + /// // which is the first page in this example. + /// let mut pager = client.list_secret_properties(None)? + /// .with_continuation_token(Some("continuation_token_from_another_pager".into())); + /// + /// while let Some(secret) = pager.try_next().await? { + /// println!("{:?}", secret.id); + /// } + /// # Ok(()) + /// # } + /// ``` + pub fn with_continuation_token(self, continuation_token: Option) -> Self { + // Set the next_token because that's what is passed to iter_from_callback to get the initial page. + if let Ok(mut token) = self.next_token.lock() { + *token = continuation_token; + } + self + } + + /// Gets the continuation token for the current page. + /// + /// Pass this to [`ItemIterator::with_continuation_token`] to create a `ItemIterator` that, when first iterated, + /// will return the current page until _after_ all items are iterated. + /// It does not continue on the next page until you call `next()` after the last item in the current page + /// because of how iterators are implemented. This may yield duplicates but will reduce the likelihood of skipping items instead. + pub fn continuation_token(&self) -> Option { + // Get the continuation_token because that will be used to start over with the current page. + self.continuation_token.clone() + } } impl futures::Stream for ItemIterator

{ @@ -429,10 +520,21 @@ impl futures::Stream for ItemIterator

{ if let Some(item) = current.next() { return task::Poll::Ready(Some(Ok(item))); } + // Reset the iterator and poll for the next page. *projected_self.current = None; } + // Set the current_token to the next page only after iterating through all items. + if let Ok(token) = projected_self.next_token.lock() { + tracing::trace!( + "updating continuation_token from {:?} to {:?}", + projected_self.continuation_token, + token + ); + *projected_self.continuation_token = token.clone(); + } + match projected_self.stream.as_mut().poll_next(cx) { task::Poll::Ready(page) => match page { Some(Ok(page)) => match page.into_items().poll_unpin(cx) { @@ -500,7 +602,7 @@ impl

PageIterator

{ /// /// This method expect a callback that accepts a single [`PagerState`] parameter, and returns a [`PagerResult`] value asynchronously. /// The `C` type parameter is the type of the next link/continuation token. It may be any [`Send`]able type. - /// The result will be an asynchronous stream of [`Result`](typespec::Result) values. + /// The result will be an asynchronous stream of [`Result`](crate::Result) values. /// /// The first time your callback is called, it will be called with [`PagerState::Initial`], indicating no next link/continuation token is present. /// @@ -523,7 +625,7 @@ impl

PageIterator

{ /// } /// let url = "https://example.com/my_paginated_api".parse().unwrap(); /// let mut base_req = Request::new(url, Method::Get); - /// let pager = PageIterator::from_callback(move |next_link: PagerState| { + /// let pager = PageIterator::from_callback(move |next_link: PagerState, ctx| { /// // The callback must be 'static, so you have to clone and move any values you want to use. /// let pipeline = pipeline.clone(); /// let api_version = api_version.clone(); @@ -542,7 +644,7 @@ impl

PageIterator

{ /// .append_pair("api-version", &api_version); /// } /// let resp = pipeline - /// .send(&Context::new(), &mut req, None) + /// .send(&ctx, &mut req, None) /// .await?; /// let (status, headers, body) = resp.deconstruct(); /// let result: ListItemsResult = json::from_json(&body)?; @@ -555,7 +657,7 @@ impl

PageIterator

{ /// None => PagerResult::Done { response: resp } /// }) /// } - /// }); + /// }, None); /// ``` /// /// To page results using headers: @@ -569,7 +671,7 @@ impl

PageIterator

{ /// } /// let url = "https://example.com/my_paginated_api".parse().unwrap(); /// let mut base_req = Request::new(url, Method::Get); - /// let pager = PageIterator::from_callback(move |continuation| { + /// let pager = PageIterator::from_callback(move |continuation, ctx| { /// // The callback must be 'static, so you have to clone and move any values you want to use. /// let pipeline = pipeline.clone(); /// let mut req = base_req.clone(); @@ -578,47 +680,34 @@ impl

PageIterator

{ /// req.insert_header("x-ms-continuation", continuation); /// } /// let resp: Response = pipeline - /// .send(&Context::new(), &mut req, None) + /// .send(&ctx, &mut req, None) /// .await? /// .into(); /// Ok(PagerResult::from_response_header(resp, &HeaderName::from_static("x-ms-continuation"))) /// } - /// }); + /// }, None); /// ``` pub fn from_callback< // This is a bit gnarly, but the only thing that differs between the WASM/non-WASM configs is the presence of Send bounds. #[cfg(not(target_arch = "wasm32"))] C: AsRef + FromStr + Send + 'static, - #[cfg(not(target_arch = "wasm32"))] F: Fn(PagerState) -> Fut + Send + 'static, + #[cfg(not(target_arch = "wasm32"))] F: Fn(PagerState, Context<'static>) -> Fut + Send + 'static, #[cfg(not(target_arch = "wasm32"))] Fut: Future>> + Send + 'static, #[cfg(target_arch = "wasm32")] C: AsRef + FromStr + 'static, - #[cfg(target_arch = "wasm32")] F: Fn(PagerState) -> Fut + 'static, + #[cfg(target_arch = "wasm32")] F: Fn(PagerState, Context<'static>) -> Fut + 'static, #[cfg(target_arch = "wasm32")] Fut: Future>> + 'static, >( make_request: F, + options: Option>, ) -> Self where - ::Err: fmt::Debug, + ::Err: std::error::Error, { + let options = options.unwrap_or_default(); let continuation_token = Arc::new(Mutex::new(None::)); - - let get_clone = continuation_token.clone(); - let set_clone = continuation_token.clone(); let stream = iter_from_callback( make_request, - move || { - if let Ok(token_guard) = get_clone.lock() { - return token_guard - .clone() - .map(|n| n.parse().expect("valid continuation_token")); - } - - None - }, - move |next_token| { - if let Ok(mut token_guard) = set_clone.lock() { - *token_guard = next_token.map(Into::into); - } - }, + options.context.clone(), + continuation_token.clone(), ); Self { @@ -627,7 +716,7 @@ impl

PageIterator

{ } } - /// Creates a [`PageIterator

`] from a raw stream of [`Result

`](typespec::Result

) values. + /// Creates a [`PageIterator

`] from a raw stream of [`Result

`](crate::Result

) values. /// /// This constructor is used when you are implementing a completely custom stream and want to use it as a pager. pub fn from_stream< @@ -643,7 +732,7 @@ impl

PageIterator

{ } } - /// Advance the `PageIterator` to the page referenced by `continuation_token`. + /// Start the `PageIterator` at the page referenced by `continuation_token`. /// /// You should call this before iterating the [`Stream`] or results may be unpredictable. /// @@ -661,10 +750,12 @@ impl

PageIterator

{ /// # async fn main() -> azure_core::Result<()> { /// let client = SecretClient::new("https://my-vault.vault.azure.net", DeveloperToolsCredential::new(None)?, None)?; /// - /// // Advance first pager to first page. + /// // Start the first pager at the first page. /// let mut pager = client.list_secret_properties(None)? /// .into_pages(); /// + /// // Continue the second pager from where the first pager left off, + /// // which is the first page in this example. /// let mut pager = client.list_secret_properties(None)? /// .into_pages() /// .with_continuation_token("continuation_token_from_another_pager".to_string()); @@ -716,78 +807,146 @@ impl

fmt::Debug for PageIterator

{ } } -#[derive(Debug, Clone, PartialEq, Eq)] -enum State { +#[derive(Debug, Clone, Eq)] +enum State { Init, - More(T), + More(C), Done, } +impl PartialEq for State { + fn eq(&self, other: &Self) -> bool { + // Only needs to compare if both states are Init or Done; internally, we don't care about any other states. + matches!( + (self, other), + (State::Init, State::Init) | (State::Done, State::Done) + ) + } +} + +#[derive(Debug)] +struct StreamState<'a, C, F> { + state: State, + make_request: F, + continuation_token: Arc>>, + ctx: Context<'a>, +} + fn iter_from_callback< P, // This is a bit gnarly, but the only thing that differs between the WASM/non-WASM configs is the presence of Send bounds. - #[cfg(not(target_arch = "wasm32"))] C: AsRef + Send + 'static, - #[cfg(not(target_arch = "wasm32"))] F: Fn(PagerState) -> Fut + Send + 'static, + #[cfg(not(target_arch = "wasm32"))] C: AsRef + FromStr + Send + 'static, + #[cfg(not(target_arch = "wasm32"))] F: Fn(PagerState, Context<'static>) -> Fut + Send + 'static, #[cfg(not(target_arch = "wasm32"))] Fut: Future>> + Send + 'static, - #[cfg(not(target_arch = "wasm32"))] G: Fn() -> Option + Send + 'static, - #[cfg(not(target_arch = "wasm32"))] S: Fn(Option<&str>) + Send + 'static, - #[cfg(target_arch = "wasm32")] C: AsRef + 'static, - #[cfg(target_arch = "wasm32")] F: Fn(PagerState) -> Fut + 'static, + #[cfg(target_arch = "wasm32")] C: AsRef + FromStr + 'static, + #[cfg(target_arch = "wasm32")] F: Fn(PagerState, Context<'static>) -> Fut + 'static, #[cfg(target_arch = "wasm32")] Fut: Future>> + 'static, - #[cfg(target_arch = "wasm32")] G: Fn() -> Option + 'static, - #[cfg(target_arch = "wasm32")] S: Fn(Option<&str>) + 'static, >( make_request: F, - get_next: G, - set_next: S, -) -> impl Stream> + 'static { + ctx: Context<'static>, + continuation_token: Arc>>, +) -> impl Stream> + 'static +where + ::Err: std::error::Error, +{ unfold( - // We flow the `make_request` callback, 'get_next', and `set_next` through the state value so that we can avoid cloning. - (State::Init, make_request, get_next, set_next), - |(mut state, make_request, get_next, set_next)| async move { - if let Some(next_token) = get_next() { - state = State::More(next_token); + StreamState { + state: State::Init, + make_request, + continuation_token, + ctx, + }, + |mut stream_state| async move { + // Get the `continuation_token` to pick up where we left off, or None for the initial page, + // but don't override the terminal `State::Done`. + if stream_state.state != State::Done { + let result = match stream_state.continuation_token.lock() { + Ok(next_token) => match next_token.as_deref() { + Some(n) => match n.parse() { + Ok(s) => Ok(State::More(s)), + Err(err) => Err(crate::Error::with_message_fn( + ErrorKind::DataConversion, + || format!("invalid continuation token: {err}"), + )), + }, + // Restart the pager if `next_token` is None indicating we resumed from before or within the first page. + None => Ok(State::Init), + }, + Err(err) => Err(crate::Error::with_message_fn(ErrorKind::Other, || { + format!("continuation token lock: {err}") + })), + }; + + match result { + Ok(state) => stream_state.state = state, + Err(err) => { + stream_state.state = State::Done; + return Some((Err(err), stream_state)); + } + } } - let result = match state { - State::Init => make_request(PagerState::Initial).await, - State::More(n) => make_request(PagerState::More(n)).await, + let result = match stream_state.state { + State::Init => { + tracing::debug!("initial page request"); + (stream_state.make_request)(PagerState::Initial, stream_state.ctx.clone()).await + } + State::More(n) => { + tracing::debug!("subsequent page request to {:?}", AsRef::::as_ref(&n)); + (stream_state.make_request)(PagerState::More(n), stream_state.ctx.clone()).await + } State::Done => { - set_next(None); + tracing::debug!("done"); + // Set the `continuation_token` to None now that we are done. + if let Ok(mut token) = stream_state.continuation_token.lock() { + *token = None; + } return None; } }; let (item, next_state) = match result { - Err(e) => return Some((Err(e), (State::Done, make_request, get_next, set_next))), + Err(e) => { + stream_state.state = State::Done; + return Some((Err(e), stream_state)); + } Ok(PagerResult::More { response, continuation: next_token, }) => { - set_next(Some(next_token.as_ref())); + // Set the `continuation_token` to the next page. + if let Ok(mut token) = stream_state.continuation_token.lock() { + *token = Some(next_token.as_ref().into()); + } (Ok(response), State::More(next_token)) } Ok(PagerResult::Done { response }) => { - set_next(None); + // Set the `continuation_token` to None now that we are done. + if let Ok(mut token) = stream_state.continuation_token.lock() { + *token = None; + } (Ok(response), State::Done) } }; - // Flow 'make_request', 'get_next', and 'set_next' through to avoid cloning - Some((item, (next_state, make_request, get_next, set_next))) + stream_state.state = next_state; + Some((item, stream_state)) }, ) } #[cfg(test)] mod tests { - use crate::http::{ - headers::{HeaderName, HeaderValue}, - pager::{PageIterator, Pager, PagerResult, PagerState}, - RawResponse, Response, StatusCode, + use crate::{ + error::ErrorKind, + http::{ + headers::{HeaderName, HeaderValue}, + pager::{PageIterator, Pager, PagerResult, PagerState}, + Context, RawResponse, Response, StatusCode, + }, }; use async_trait::async_trait; use futures::{StreamExt as _, TryStreamExt as _}; use serde::Deserialize; - use std::collections::HashMap; + use std::{collections::HashMap, future::Future, pin::Pin}; #[derive(Deserialize, Debug, PartialEq, Eq)] struct Page { @@ -808,82 +967,88 @@ mod tests { #[tokio::test] async fn callback_item_pagination() { - let pager: Pager = Pager::from_callback(|continuation| async move { - match continuation { - PagerState::Initial => Ok(PagerResult::More { - response: RawResponse::from_bytes( - StatusCode::Ok, - HashMap::from([( - HeaderName::from_static("x-test-header"), - HeaderValue::from_static("page-1"), - )]) + let pager: Pager = Pager::from_callback( + |continuation: PagerState, _ctx| async move { + match continuation { + PagerState::Initial => Ok(PagerResult::More { + response: RawResponse::from_bytes( + StatusCode::Ok, + HashMap::from([( + HeaderName::from_static("x-test-header"), + HeaderValue::from_static("page-1"), + )]) + .into(), + r#"{"items":[1],"page":1}"#, + ) .into(), - r#"{"items":[1],"page":1}"#, - ) - .into(), - continuation: "1", - }), - PagerState::More("1") => Ok(PagerResult::More { - response: RawResponse::from_bytes( - StatusCode::Ok, - HashMap::from([( - HeaderName::from_static("x-test-header"), - HeaderValue::from_static("page-2"), - )]) + continuation: "1".into(), + }), + PagerState::More(ref i) if i == "1" => Ok(PagerResult::More { + response: RawResponse::from_bytes( + StatusCode::Ok, + HashMap::from([( + HeaderName::from_static("x-test-header"), + HeaderValue::from_static("page-2"), + )]) + .into(), + r#"{"items":[2],"page":2}"#, + ) .into(), - r#"{"items":[2],"page":2}"#, - ) - .into(), - continuation: "2", - }), - PagerState::More("2") => Ok(PagerResult::Done { - response: RawResponse::from_bytes( - StatusCode::Ok, - HashMap::from([( - HeaderName::from_static("x-test-header"), - HeaderValue::from_static("page-3"), - )]) + continuation: "2".into(), + }), + PagerState::More(ref i) if i == "2" => Ok(PagerResult::Done { + response: RawResponse::from_bytes( + StatusCode::Ok, + HashMap::from([( + HeaderName::from_static("x-test-header"), + HeaderValue::from_static("page-3"), + )]) + .into(), + r#"{"items":[3],"page":3}"#, + ) .into(), - r#"{"items":[3],"page":3}"#, - ) - .into(), - }), - _ => { - panic!("Unexpected continuation value") + }), + _ => { + panic!("Unexpected continuation value") + } } - } - }); + }, + None, + ); let items: Vec = pager.try_collect().await.unwrap(); assert_eq!(vec![1, 2, 3], items.as_slice()) } #[tokio::test] async fn callback_item_pagination_error() { - let pager: Pager = Pager::from_callback(|continuation| async move { - match continuation { - PagerState::Initial => Ok(PagerResult::More { - response: RawResponse::from_bytes( - StatusCode::Ok, - HashMap::from([( - HeaderName::from_static("x-test-header"), - HeaderValue::from_static("page-1"), - )]) + let pager: Pager = Pager::from_callback( + |continuation: PagerState, _ctx| async move { + match continuation { + PagerState::Initial => Ok(PagerResult::More { + response: RawResponse::from_bytes( + StatusCode::Ok, + HashMap::from([( + HeaderName::from_static("x-test-header"), + HeaderValue::from_static("page-1"), + )]) + .into(), + r#"{"items":[1],"page":1}"#, + ) .into(), - r#"{"items":[1],"page":1}"#, - ) - .into(), - continuation: "1", - }), - PagerState::More("1") => Err(typespec::Error::with_message( - typespec::error::ErrorKind::Other, - "yon request didst fail", - )), - _ => { - panic!("Unexpected continuation value") + continuation: "1".into(), + }), + PagerState::More(ref i) if i == "1" => Err(crate::Error::with_message( + crate::error::ErrorKind::Other, + "yon request didst fail", + )), + _ => { + panic!("Unexpected continuation value") + } } - } - }); - let pages: Vec> = pager + }, + None, + ); + let pages: Vec> = pager .into_pages() .then(|r| async move { let r = r?; @@ -909,59 +1074,15 @@ mod tests { ); let err = pages[1].as_ref().unwrap_err(); - assert_eq!(&typespec::error::ErrorKind::Other, err.kind()); + assert_eq!(&crate::error::ErrorKind::Other, err.kind()); assert_eq!("yon request didst fail", format!("{}", err)); } #[tokio::test] async fn page_iterator_with_continuation_token() { - let make_callback = || { - |continuation: PagerState| async move { - match continuation.as_deref() { - PagerState::Initial => Ok(PagerResult::More { - response: RawResponse::from_bytes( - StatusCode::Ok, - Default::default(), - r#"{"items":[1],"page":1}"#, - ) - .into(), - continuation: "next-token-1".to_string(), - }), - PagerState::More("next-token-1") => Ok(PagerResult::More { - response: RawResponse::from_bytes( - StatusCode::Ok, - HashMap::from([( - HeaderName::from_static("x-test-header"), - HeaderValue::from_static("page-2"), - )]) - .into(), - r#"{"items":[2],"page":2}"#, - ) - .into(), - continuation: "next-token-2".to_string(), - }), - PagerState::More("next-token-2") => Ok(PagerResult::Done { - response: RawResponse::from_bytes( - StatusCode::Ok, - HashMap::from([( - HeaderName::from_static("x-test-header"), - HeaderValue::from_static("page-3"), - )]) - .into(), - r#"{"items":[3]}"#, - ) - .into(), - }), - _ => { - panic!("Unexpected continuation value: {:?}", continuation) - } - } - } - }; - // Create the first PageIterator. let mut first_pager: PageIterator> = - PageIterator::from_callback(make_callback()); + PageIterator::from_callback(make_three_page_callback(), None); // Should start with no continuation_token. assert_eq!(first_pager.continuation_token(), None); @@ -975,7 +1096,7 @@ mod tests { .into_body() .expect("expected page"); assert_eq!(first_page.page, Some(1)); - assert_eq!(first_page.items, vec![1]); + assert_eq!(first_page.items, vec![1, 2, 3]); // continuation_token should point to second page. let continuation_token = first_pager @@ -985,7 +1106,7 @@ mod tests { // Create the second PageIterator. let mut second_pager: PageIterator> = - PageIterator::from_callback(make_callback()) + PageIterator::from_callback(make_three_page_callback(), None) .with_continuation_token(continuation_token); // Should start with link to second page. @@ -1003,7 +1124,7 @@ mod tests { .into_body() .expect("expected page"); assert_eq!(second_page.page, Some(2)); - assert_eq!(second_page.items, vec![2]); + assert_eq!(second_page.items, vec![4, 5, 6]); assert_eq!( second_pager.continuation_token(), Some("next-token-2".into()) @@ -1018,7 +1139,409 @@ mod tests { .into_body() .expect("expected page"); assert_eq!(last_page.page, None); - assert_eq!(last_page.items, vec![3]); + assert_eq!(last_page.items, vec![7, 8, 9]); assert_eq!(second_pager.continuation_token(), None); } + + #[tokio::test] + async fn page_iterator_from_item_iterator_after_first_page() { + // Create an ItemIterator and consume all items from first page. + let mut item_pager: Pager = Pager::from_callback(make_three_page_callback(), None); + + // Should start with no continuation_token. + assert_eq!(item_pager.continuation_token(), None); + + // Consume all three items from the first page. + let first_item = item_pager + .next() + .await + .expect("expected first item") + .expect("expected successful first item"); + assert_eq!(first_item, 1); + + let second_item = item_pager + .next() + .await + .expect("expected second item") + .expect("expected successful second item"); + assert_eq!(second_item, 2); + + let third_item = item_pager + .next() + .await + .expect("expected third item") + .expect("expected successful third item"); + assert_eq!(third_item, 3); + + // Convert to PageIterator after consuming first page. + let mut page_pager = item_pager.into_pages(); + + // Should start with None initially. + assert_eq!(page_pager.continuation_token(), None); + + // Verify we start over with the first page again (ItemIterator.continuation_token() was None). + let first_page = page_pager + .next() + .await + .expect("expected first page") + .expect("expected successful first page") + .into_body() + .expect("expected page"); + assert_eq!(first_page.page, Some(1)); + assert_eq!(first_page.items, vec![1, 2, 3]); + + // continuation_token should now point to second page. + let continuation_token = page_pager + .continuation_token() + .expect("expected continuation_token from first page"); + assert_eq!(continuation_token, "next-token-1"); + } + + #[tokio::test] + async fn page_iterator_from_item_iterator_second_page_first_item() { + // Create an ItemIterator and consume items up to first item of second page. + let mut item_pager: Pager = Pager::from_callback(make_three_page_callback(), None); + + // Should start with no continuation_token. + assert_eq!(item_pager.continuation_token(), None); + + // Consume all three items from the first page. + let first_item = item_pager + .next() + .await + .expect("expected first item") + .expect("expected successful first item"); + assert_eq!(first_item, 1); + + let second_item = item_pager + .next() + .await + .expect("expected second item") + .expect("expected successful second item"); + assert_eq!(second_item, 2); + + let third_item = item_pager + .next() + .await + .expect("expected third item") + .expect("expected successful third item"); + assert_eq!(third_item, 3); + + // Get first item from second page. + let fourth_item = item_pager + .next() + .await + .expect("expected fourth item") + .expect("expected successful fourth item"); + assert_eq!(fourth_item, 4); + + // Convert to PageIterator after consuming first item of second page. + let mut page_pager = item_pager.into_pages(); + + // Should start with second page since that's where we were. + assert_eq!(page_pager.continuation_token(), Some("next-token-1".into())); + + // Get second page - should be the second page. + let second_page = page_pager + .next() + .await + .expect("expected second page") + .expect("expected successful second page") + .into_body() + .expect("expected page"); + assert_eq!(second_page.page, Some(2)); + assert_eq!(second_page.items, vec![4, 5, 6]); + + // continuation_token should now point to third page. + let continuation_token = page_pager + .continuation_token() + .expect("expected continuation_token from second page"); + assert_eq!(continuation_token, "next-token-2"); + } + + #[tokio::test] + async fn item_iterator_with_continuation_token() { + // Create the first ItemIterator. + let mut first_pager: Pager = Pager::from_callback(make_three_page_callback(), None); + + // Should start with no continuation_token. + assert_eq!(first_pager.continuation_token(), None); + + // Get first item from first page. + let first_item = first_pager + .next() + .await + .expect("expected first item") + .expect("expected successful first item"); + assert_eq!(first_item, 1); + + // Get second item from first page. + let second_item = first_pager + .next() + .await + .expect("expected second item") + .expect("expected successful second item"); + assert_eq!(second_item, 2); + + // continuation_token should point to current page after processing some, but not all, items. + let continuation_token = first_pager.continuation_token(); + assert_eq!(continuation_token, None); + + // Create the second ItemIterator with continuation token. + let mut second_pager: Pager = Pager::from_callback(make_three_page_callback(), None) + .with_continuation_token(continuation_token); + + // Should start with link to first page. + assert_eq!(second_pager.continuation_token(), None); + + // When continuing with a continuation token, we should start over from the + // beginning of the page, not where we left off in the item stream. + // This means we should get the first item of the first page (1), not the + // third item of the first page (3). + let first_item_second_pager = second_pager + .next() + .await + .expect("expected first item from second pager") + .expect("expected successful first item from second pager"); + assert_eq!(first_item_second_pager, 1); + + // Get remaining items. + let items: Vec = second_pager.try_collect().await.unwrap(); + assert_eq!(items.as_slice(), vec![2, 3, 4, 5, 6, 7, 8, 9]); + } + + #[tokio::test] + async fn item_iterator_continuation_second_page_second_item() { + // Create the first ItemIterator. + let mut first_pager: Pager = Pager::from_callback(make_three_page_callback(), None); + + // Should start with no continuation_token. + assert_eq!(first_pager.continuation_token(), None); + + // Iterate to the second item of the second page. + // First page: items 1, 2, 3 + let first_item = first_pager + .next() + .await + .expect("expected first item") + .expect("expected successful first item"); + assert_eq!(first_item, 1); + + let second_item = first_pager + .next() + .await + .expect("expected second item") + .expect("expected successful second item"); + assert_eq!(second_item, 2); + + let third_item = first_pager + .next() + .await + .expect("expected third item") + .expect("expected successful third item"); + assert_eq!(third_item, 3); + + // Second page: item 4 (first of second page) + let fourth_item = first_pager + .next() + .await + .expect("expected fourth item") + .expect("expected successful fourth item"); + assert_eq!(fourth_item, 4); + + // Second page: item 5 (second of second page) + let fifth_item = first_pager + .next() + .await + .expect("expected fifth item") + .expect("expected successful fifth item"); + assert_eq!(fifth_item, 5); + + // Get continuation token - should point to current page (second page). + let continuation_token = first_pager.continuation_token(); + assert_eq!(continuation_token.as_deref(), Some("next-token-1")); + + // Create the second ItemIterator with continuation token. + let mut second_pager: Pager = Pager::from_callback(make_three_page_callback(), None) + .with_continuation_token(continuation_token); + + // When continuing with a continuation token, we should start over from the + // beginning of the current page (second page), not where we left off. + // This means we should get the first item of the second page (4). + let first_item_second_pager = second_pager + .next() + .await + .expect("expected first item from second pager") + .expect("expected successful first item from second pager"); + assert_eq!(first_item_second_pager, 4); + + // Get remaining items. + let items: Vec = second_pager.try_collect().await.unwrap(); + assert_eq!(items.as_slice(), vec![5, 6, 7, 8, 9]); + } + + #[tokio::test] + async fn item_iterator_continuation_after_first_page() { + // Create the first ItemIterator. + let mut first_pager: Pager = Pager::from_callback(make_three_page_callback(), None); + + // Should start with no continuation_token. + assert_eq!(first_pager.continuation_token(), None); + + // Iterate past the third item of the first page (all items of first page). + let first_item = first_pager + .next() + .await + .expect("expected first item") + .expect("expected successful first item"); + assert_eq!(first_item, 1); + + let second_item = first_pager + .next() + .await + .expect("expected second item") + .expect("expected successful second item"); + assert_eq!(second_item, 2); + + let third_item = first_pager + .next() + .await + .expect("expected third item") + .expect("expected successful third item"); + assert_eq!(third_item, 3); + + // Get continuation token after finishing the first page - should still point to current page (first page). + let continuation_token = first_pager.continuation_token(); + assert_eq!(continuation_token, None); + + // Create the second ItemIterator with continuation token. + let mut second_pager: Pager = Pager::from_callback(make_three_page_callback(), None) + .with_continuation_token(continuation_token); + + // When continuing with a continuation token after finishing a page, we should + // start from the beginning of the current page. + // This means we should get the first item of the second page (4). + let first_item_second_pager = second_pager + .next() + .await + .expect("expected first item from first pager") + .expect("expected successful first item from first pager"); + assert_eq!(first_item_second_pager, 1); + + // Get remaining items. + let items: Vec = second_pager.try_collect().await.unwrap(); + assert_eq!(items.as_slice(), vec![2, 3, 4, 5, 6, 7, 8, 9]); + } + + /// A continuation token type that always fails to parse, used to test FromStr constraint. + #[derive(Debug, Clone, PartialEq, Eq)] + struct ContinuationToken(String); + + impl AsRef for ContinuationToken { + fn as_ref(&self) -> &str { + &self.0 + } + } + + impl std::str::FromStr for ContinuationToken { + type Err = std::io::Error; + + fn from_str(_s: &str) -> Result { + // Always fail to parse + Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "ContinuationToken parsing always fails", + )) + } + } + + #[tokio::test] + async fn callback_item_pagination_from_str_error() { + let mut pager: Pager = Pager::from_callback( + |continuation: PagerState, _ctx| async move { + match continuation { + PagerState::Initial => Ok(PagerResult::More { + response: RawResponse::from_bytes( + StatusCode::Ok, + HashMap::from([( + HeaderName::from_static("x-test-header"), + HeaderValue::from_static("page-1"), + )]) + .into(), + r#"{"items":[1],"page":1}"#, + ) + .into(), + // cspell:ignore unparseable + continuation: ContinuationToken("unparseable-token".to_string()), + }), + _ => { + panic!("Unexpected continuation value: {:?}", continuation) + } + } + }, + None, + ); + + // Get the first item from the first page. + let first_item = pager.try_next().await.expect("expected first page"); + assert_eq!(first_item, Some(1)); + + // Attempt to get the second page, which will attempt to parse the continuation token that should fail. + assert!( + matches!(pager.try_next().await, Err(err) if err.kind() == &ErrorKind::DataConversion) + ); + } + + #[allow(clippy::type_complexity)] + fn make_three_page_callback() -> impl Fn( + PagerState, + Context<'_>, + ) -> Pin< + Box, String>>> + Send>, + > + Send + + 'static { + |continuation: PagerState, _ctx| { + Box::pin(async move { + match continuation.as_deref() { + PagerState::Initial => Ok(PagerResult::More { + response: RawResponse::from_bytes( + StatusCode::Ok, + Default::default(), + r#"{"items":[1,2,3],"page":1}"#, + ) + .into(), + continuation: "next-token-1".to_string(), + }), + PagerState::More("next-token-1") => Ok(PagerResult::More { + response: RawResponse::from_bytes( + StatusCode::Ok, + HashMap::from([( + HeaderName::from_static("x-test-header"), + HeaderValue::from_static("page-2"), + )]) + .into(), + r#"{"items":[4,5,6],"page":2}"#, + ) + .into(), + continuation: "next-token-2".to_string(), + }), + PagerState::More("next-token-2") => Ok(PagerResult::Done { + response: RawResponse::from_bytes( + StatusCode::Ok, + HashMap::from([( + HeaderName::from_static("x-test-header"), + HeaderValue::from_static("page-3"), + )]) + .into(), + r#"{"items":[7,8,9]}"#, + ) + .into(), + }), + _ => { + panic!("Unexpected continuation value: {:?}", continuation) + } + } + }) + } + } } diff --git a/sdk/core/azure_core/src/http/poller.rs b/sdk/core/azure_core/src/http/poller.rs index 4e733c2a39..a304635040 100644 --- a/sdk/core/azure_core/src/http/poller.rs +++ b/sdk/core/azure_core/src/http/poller.rs @@ -444,10 +444,10 @@ where /// }, None); /// ``` pub fn from_callback< - #[cfg(not(target_arch = "wasm32"))] N: Send + 'static, + #[cfg(not(target_arch = "wasm32"))] N: AsRef + Send + 'static, #[cfg(not(target_arch = "wasm32"))] Fun: Fn(PollerState) -> Fut + Send + 'static, #[cfg(not(target_arch = "wasm32"))] Fut: Future>> + Send + 'static, - #[cfg(target_arch = "wasm32")] N: 'static, + #[cfg(target_arch = "wasm32")] N: AsRef + 'static, #[cfg(target_arch = "wasm32")] Fun: Fn(PollerState) -> Fut + 'static, #[cfg(target_arch = "wasm32")] Fut: Future>> + 'static, >( @@ -582,10 +582,10 @@ enum State { fn create_poller_stream< M, F: Format, - #[cfg(not(target_arch = "wasm32"))] N: Send + 'static, + #[cfg(not(target_arch = "wasm32"))] N: AsRef + Send + 'static, #[cfg(not(target_arch = "wasm32"))] Fun: Fn(PollerState) -> Fut + Send + 'static, #[cfg(not(target_arch = "wasm32"))] Fut: Future>> + Send + 'static, - #[cfg(target_arch = "wasm32")] N: 'static, + #[cfg(target_arch = "wasm32")] N: AsRef + 'static, #[cfg(target_arch = "wasm32")] Fun: Fn(PollerState) -> Fut + 'static, #[cfg(target_arch = "wasm32")] Fut: Future>> + 'static, >( @@ -617,9 +617,21 @@ where (State::Init, make_request, Some(target_tx)), move |(state, make_request, target_tx)| async move { let result = match state { - State::Init => make_request(PollerState::Initial).await, - State::InProgress(n) => make_request(PollerState::More(n)).await, - State::Done => return None, + State::Init => { + tracing::debug!("initial operation request"); + make_request(PollerState::Initial).await + } + State::InProgress(n) => { + tracing::debug!( + "subsequent operation request to {:?}", + AsRef::::as_ref(&n) + ); + make_request(PollerState::More(n)).await + } + State::Done => { + tracing::debug!("done"); + return None; + } }; let (item, next_state) = match result { Err(e) => return Some((Err(e), (State::Done, make_request, target_tx))), @@ -830,7 +842,7 @@ mod tests { PollerStatus::InProgress => Ok(PollerResult::InProgress { response, retry_after: Some(Duration::ZERO), - next: (), + next: "", }), _ => Ok(PollerResult::Done { response }), } @@ -915,7 +927,7 @@ mod tests { PollerStatus::InProgress => Ok(PollerResult::InProgress { response, retry_after: Some(Duration::ZERO), - next: (), + next: "", }), _ => Ok(PollerResult::Done { response }), } @@ -1001,7 +1013,7 @@ mod tests { PollerStatus::InProgress => Ok(PollerResult::InProgress { response, retry_after: Some(Duration::ZERO), - next: (), + next: "", }), _ => Ok(PollerResult::Done { response }), } @@ -1087,7 +1099,7 @@ mod tests { PollerStatus::InProgress => Ok(PollerResult::InProgress { response, retry_after: Some(Duration::ZERO), - next: (), + next: "", }), PollerStatus::Succeeded => { // Return the status response with a callback to fetch the final resource @@ -1192,7 +1204,7 @@ mod tests { PollerStatus::InProgress => Ok(PollerResult::InProgress { response, retry_after: Some(Duration::ZERO), - next: (), + next: "", }), PollerStatus::Succeeded => { // Return the status response with a callback to fetch the final resource @@ -1311,7 +1323,7 @@ mod tests { PollerStatus::InProgress => Ok(PollerResult::InProgress { response, retry_after: Some(Duration::ZERO), - next: (), + next: "", }), PollerStatus::Succeeded => { // Return the status response with a callback @@ -1397,7 +1409,7 @@ mod tests { PollerStatus::InProgress => Ok(PollerResult::InProgress { response, retry_after: Some(Duration::ZERO), - next: (), + next: "", }), _ => Ok(PollerResult::Done { response }), } @@ -1483,7 +1495,7 @@ mod tests { PollerStatus::InProgress => Ok(PollerResult::InProgress { response, retry_after: Some(Duration::ZERO), - next: (), + next: "", }), PollerStatus::Succeeded => { // Return the status response with a callback @@ -1591,7 +1603,7 @@ mod tests { PollerStatus::InProgress => Ok(PollerResult::InProgress { response, retry_after: Some(Duration::ZERO), - next: (), + next: "", }), PollerStatus::Succeeded => { // The final result is already in the status response itself @@ -1703,7 +1715,7 @@ mod tests { PollerStatus::InProgress => Ok(PollerResult::InProgress { response, retry_after: Some(Duration::ZERO), - next: (), + next: "", }), PollerStatus::Succeeded => { // The final result is already in the status response itself diff --git a/sdk/core/azure_core_test/src/recording.rs b/sdk/core/azure_core_test/src/recording.rs index fe36283130..ad389be0c6 100644 --- a/sdk/core/azure_core_test/src/recording.rs +++ b/sdk/core/azure_core_test/src/recording.rs @@ -220,7 +220,7 @@ impl Recording { /// ``` /// # let recording = azure_core_test::Recording::with_seed(); /// let dek: [u8; 32] = recording.random(); - /// # assert_eq!(typespec_client_core::base64::encode(dek), "HumPRAN6RqKWf0YhFV2CAFWu/8L/pwh0LRzeam5VlGo="); + /// # assert_eq!(azure_core::base64::encode(dek), "HumPRAN6RqKWf0YhFV2CAFWu/8L/pwh0LRzeam5VlGo="); /// ``` /// /// Generate a UUID. diff --git a/sdk/cosmos/azure_data_cosmos/src/pipeline/mod.rs b/sdk/cosmos/azure_data_cosmos/src/pipeline/mod.rs index f0b8aad0d7..083aa0c7cc 100644 --- a/sdk/cosmos/azure_data_cosmos/src/pipeline/mod.rs +++ b/sdk/cosmos/azure_data_cosmos/src/pipeline/mod.rs @@ -6,7 +6,7 @@ mod signature_target; pub use authorization_policy::AuthorizationPolicy; use azure_core::http::{ - pager::PagerState, + pager::{PagerOptions, PagerState}, request::{options::ContentType, Request}, response::Response, ClientOptions, Context, Method, RawResponse, RetryOptions, @@ -115,25 +115,30 @@ impl CosmosPipeline { // We have to double-clone here. // First we clone the pipeline to pass it in to the closure let pipeline = self.pipeline.clone(); - let ctx = ctx.with_value(resource_link).into_owned(); - Ok(FeedPager::from_callback(move |continuation| { - // Then we have to clone it again to pass it in to the async block. - // This is because Pageable can't borrow any data, it has to own it all. - // That's probably good, because it means a Pageable can outlive the client that produced it, but it requires some extra cloning. - let pipeline = pipeline.clone(); - let mut req = base_request.clone(); - let ctx = ctx.clone(); - async move { - if let PagerState::More(continuation) = continuation { - req.insert_header(constants::CONTINUATION, continuation); + let options = PagerOptions { + context: ctx.with_value(resource_link).into_owned(), + }; + Ok(FeedPager::from_callback( + move |continuation, ctx| { + // Then we have to clone it again to pass it in to the async block. + // This is because Pageable can't borrow any data, it has to own it all. + // That's probably good, because it means a Pageable can outlive the client that produced it, but it requires some extra cloning. + let pipeline = pipeline.clone(); + let mut req = base_request.clone(); + let ctx = ctx.clone(); + async move { + if let PagerState::More(continuation) = continuation { + req.insert_header(constants::CONTINUATION, continuation); + } + + let resp = pipeline.send(&ctx, &mut req, None).await?; + let page = FeedPage::::from_response(resp).await?; + + Ok(page.into()) } - - let resp = pipeline.send(&ctx, &mut req, None).await?; - let page = FeedPage::::from_response(resp).await?; - - Ok(page.into()) - } - })) + }, + Some(options), + )) } /// Helper function to read a throughput offer given a resource ID. diff --git a/sdk/keyvault/azure_security_keyvault_certificates/CHANGELOG.md b/sdk/keyvault/azure_security_keyvault_certificates/CHANGELOG.md index fac9382a66..9d6cbe443e 100644 --- a/sdk/keyvault/azure_security_keyvault_certificates/CHANGELOG.md +++ b/sdk/keyvault/azure_security_keyvault_certificates/CHANGELOG.md @@ -7,6 +7,10 @@ ### Breaking Changes - `CertificateClient::create_certificate()` now returns a `Poller`. +- `CertificateClientListCertificatePropertiesOptions::method_options` is now `PagerOptions`. +- `CertificateClientListCertificatePropertiesVersionsOptions::method_options` is now `PagerOptions`. +- `CertificateClientListDeletedCertificatePropertiesOptions::method_options` is now `PagerOptions`. +- `CertificateClientListIssuerPropertiesOptions::method_options` is now `PagerOptions`. - Removed `CertificateClient::begin_create_certificate()`. - Removed `CertificateClient::resume_create_certificate()`. - Removed `wait()` function from `Poller`. diff --git a/sdk/keyvault/azure_security_keyvault_certificates/src/generated/clients/certificate_client.rs b/sdk/keyvault/azure_security_keyvault_certificates/src/generated/clients/certificate_client.rs index 61363c960c..47e28b95ee 100644 --- a/sdk/keyvault/azure_security_keyvault_certificates/src/generated/clients/certificate_client.rs +++ b/sdk/keyvault/azure_security_keyvault_certificates/src/generated/clients/certificate_client.rs @@ -689,51 +689,53 @@ impl CertificateClient { .append_pair("maxresults", &maxresults.to_string()); } let api_version = self.api_version.clone(); - Ok(Pager::from_callback(move |next_link: PagerState| { - let url = match next_link { - PagerState::More(next_link) => { - let qp = next_link - .query_pairs() - .filter(|(name, _)| name.ne("api-version")); - let mut next_link = next_link.clone(); - next_link - .query_pairs_mut() - .clear() - .extend_pairs(qp) - .append_pair("api-version", &api_version); - next_link + Ok(Pager::from_callback( + move |next_link: PagerState, ctx| { + let url = match next_link { + PagerState::More(next_link) => { + let qp = next_link + .query_pairs() + .filter(|(name, _)| name.ne("api-version")); + let mut next_link = next_link.clone(); + next_link + .query_pairs_mut() + .clear() + .extend_pairs(qp) + .append_pair("api-version", &api_version); + next_link + } + PagerState::Initial => first_url.clone(), + }; + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let pipeline = pipeline.clone(); + async move { + let rsp = pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + let (status, headers, body) = rsp.deconstruct(); + let res: ListCertificatePropertiesResult = json::from_json(&body)?; + let rsp = RawResponse::from_bytes(status, headers, body).into(); + Ok(match res.next_link { + Some(next_link) if !next_link.is_empty() => PagerResult::More { + response: rsp, + continuation: next_link.parse()?, + }, + _ => PagerResult::Done { response: rsp }, + }) } - PagerState::Initial => first_url.clone(), - }; - let mut request = Request::new(url, Method::Get); - request.insert_header("accept", "application/json"); - let ctx = options.method_options.context.clone(); - let pipeline = pipeline.clone(); - async move { - let rsp = pipeline - .send( - &ctx, - &mut request, - Some(PipelineSendOptions { - check_success: CheckSuccessOptions { - success_codes: &[200], - }, - ..Default::default() - }), - ) - .await?; - let (status, headers, body) = rsp.deconstruct(); - let res: ListCertificatePropertiesResult = json::from_json(&body)?; - let rsp = RawResponse::from_bytes(status, headers, body).into(); - Ok(match res.next_link { - Some(next_link) if !next_link.is_empty() => PagerResult::More { - response: rsp, - continuation: next_link.parse()?, - }, - _ => PagerResult::Done { response: rsp }, - }) - } - })) + }, + Some(options.method_options), + )) } /// List the versions of a certificate. @@ -772,51 +774,53 @@ impl CertificateClient { .append_pair("maxresults", &maxresults.to_string()); } let api_version = self.api_version.clone(); - Ok(Pager::from_callback(move |next_link: PagerState| { - let url = match next_link { - PagerState::More(next_link) => { - let qp = next_link - .query_pairs() - .filter(|(name, _)| name.ne("api-version")); - let mut next_link = next_link.clone(); - next_link - .query_pairs_mut() - .clear() - .extend_pairs(qp) - .append_pair("api-version", &api_version); - next_link + Ok(Pager::from_callback( + move |next_link: PagerState, ctx| { + let url = match next_link { + PagerState::More(next_link) => { + let qp = next_link + .query_pairs() + .filter(|(name, _)| name.ne("api-version")); + let mut next_link = next_link.clone(); + next_link + .query_pairs_mut() + .clear() + .extend_pairs(qp) + .append_pair("api-version", &api_version); + next_link + } + PagerState::Initial => first_url.clone(), + }; + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let pipeline = pipeline.clone(); + async move { + let rsp = pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + let (status, headers, body) = rsp.deconstruct(); + let res: ListCertificatePropertiesResult = json::from_json(&body)?; + let rsp = RawResponse::from_bytes(status, headers, body).into(); + Ok(match res.next_link { + Some(next_link) if !next_link.is_empty() => PagerResult::More { + response: rsp, + continuation: next_link.parse()?, + }, + _ => PagerResult::Done { response: rsp }, + }) } - PagerState::Initial => first_url.clone(), - }; - let mut request = Request::new(url, Method::Get); - request.insert_header("accept", "application/json"); - let ctx = options.method_options.context.clone(); - let pipeline = pipeline.clone(); - async move { - let rsp = pipeline - .send( - &ctx, - &mut request, - Some(PipelineSendOptions { - check_success: CheckSuccessOptions { - success_codes: &[200], - }, - ..Default::default() - }), - ) - .await?; - let (status, headers, body) = rsp.deconstruct(); - let res: ListCertificatePropertiesResult = json::from_json(&body)?; - let rsp = RawResponse::from_bytes(status, headers, body).into(); - Ok(match res.next_link { - Some(next_link) if !next_link.is_empty() => PagerResult::More { - response: rsp, - continuation: next_link.parse()?, - }, - _ => PagerResult::Done { response: rsp }, - }) - } - })) + }, + Some(options.method_options), + )) } /// Lists the deleted certificates in the specified vault currently available for recovery. @@ -851,51 +855,53 @@ impl CertificateClient { .append_pair("maxresults", &maxresults.to_string()); } let api_version = self.api_version.clone(); - Ok(Pager::from_callback(move |next_link: PagerState| { - let url = match next_link { - PagerState::More(next_link) => { - let qp = next_link - .query_pairs() - .filter(|(name, _)| name.ne("api-version")); - let mut next_link = next_link.clone(); - next_link - .query_pairs_mut() - .clear() - .extend_pairs(qp) - .append_pair("api-version", &api_version); - next_link + Ok(Pager::from_callback( + move |next_link: PagerState, ctx| { + let url = match next_link { + PagerState::More(next_link) => { + let qp = next_link + .query_pairs() + .filter(|(name, _)| name.ne("api-version")); + let mut next_link = next_link.clone(); + next_link + .query_pairs_mut() + .clear() + .extend_pairs(qp) + .append_pair("api-version", &api_version); + next_link + } + PagerState::Initial => first_url.clone(), + }; + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let pipeline = pipeline.clone(); + async move { + let rsp = pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + let (status, headers, body) = rsp.deconstruct(); + let res: ListDeletedCertificatePropertiesResult = json::from_json(&body)?; + let rsp = RawResponse::from_bytes(status, headers, body).into(); + Ok(match res.next_link { + Some(next_link) if !next_link.is_empty() => PagerResult::More { + response: rsp, + continuation: next_link.parse()?, + }, + _ => PagerResult::Done { response: rsp }, + }) } - PagerState::Initial => first_url.clone(), - }; - let mut request = Request::new(url, Method::Get); - request.insert_header("accept", "application/json"); - let ctx = options.method_options.context.clone(); - let pipeline = pipeline.clone(); - async move { - let rsp = pipeline - .send( - &ctx, - &mut request, - Some(PipelineSendOptions { - check_success: CheckSuccessOptions { - success_codes: &[200], - }, - ..Default::default() - }), - ) - .await?; - let (status, headers, body) = rsp.deconstruct(); - let res: ListDeletedCertificatePropertiesResult = json::from_json(&body)?; - let rsp = RawResponse::from_bytes(status, headers, body).into(); - Ok(match res.next_link { - Some(next_link) if !next_link.is_empty() => PagerResult::More { - response: rsp, - continuation: next_link.parse()?, - }, - _ => PagerResult::Done { response: rsp }, - }) - } - })) + }, + Some(options.method_options), + )) } /// List certificate issuers for a specified key vault. @@ -924,51 +930,53 @@ impl CertificateClient { .append_pair("maxresults", &maxresults.to_string()); } let api_version = self.api_version.clone(); - Ok(Pager::from_callback(move |next_link: PagerState| { - let url = match next_link { - PagerState::More(next_link) => { - let qp = next_link - .query_pairs() - .filter(|(name, _)| name.ne("api-version")); - let mut next_link = next_link.clone(); - next_link - .query_pairs_mut() - .clear() - .extend_pairs(qp) - .append_pair("api-version", &api_version); - next_link + Ok(Pager::from_callback( + move |next_link: PagerState, ctx| { + let url = match next_link { + PagerState::More(next_link) => { + let qp = next_link + .query_pairs() + .filter(|(name, _)| name.ne("api-version")); + let mut next_link = next_link.clone(); + next_link + .query_pairs_mut() + .clear() + .extend_pairs(qp) + .append_pair("api-version", &api_version); + next_link + } + PagerState::Initial => first_url.clone(), + }; + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let pipeline = pipeline.clone(); + async move { + let rsp = pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + let (status, headers, body) = rsp.deconstruct(); + let res: ListIssuerPropertiesResult = json::from_json(&body)?; + let rsp = RawResponse::from_bytes(status, headers, body).into(); + Ok(match res.next_link { + Some(next_link) if !next_link.is_empty() => PagerResult::More { + response: rsp, + continuation: next_link.parse()?, + }, + _ => PagerResult::Done { response: rsp }, + }) } - PagerState::Initial => first_url.clone(), - }; - let mut request = Request::new(url, Method::Get); - request.insert_header("accept", "application/json"); - let ctx = options.method_options.context.clone(); - let pipeline = pipeline.clone(); - async move { - let rsp = pipeline - .send( - &ctx, - &mut request, - Some(PipelineSendOptions { - check_success: CheckSuccessOptions { - success_codes: &[200], - }, - ..Default::default() - }), - ) - .await?; - let (status, headers, body) = rsp.deconstruct(); - let res: ListIssuerPropertiesResult = json::from_json(&body)?; - let rsp = RawResponse::from_bytes(status, headers, body).into(); - Ok(match res.next_link { - Some(next_link) if !next_link.is_empty() => PagerResult::More { - response: rsp, - continuation: next_link.parse()?, - }, - _ => PagerResult::Done { response: rsp }, - }) - } - })) + }, + Some(options.method_options), + )) } /// Merges a certificate or a certificate chain with a key pair existing on the server. diff --git a/sdk/keyvault/azure_security_keyvault_certificates/src/generated/models/method_options.rs b/sdk/keyvault/azure_security_keyvault_certificates/src/generated/models/method_options.rs index 7430c21e9b..44e1dcb749 100644 --- a/sdk/keyvault/azure_security_keyvault_certificates/src/generated/models/method_options.rs +++ b/sdk/keyvault/azure_security_keyvault_certificates/src/generated/models/method_options.rs @@ -3,7 +3,10 @@ // Licensed under the MIT License. See License.txt in the project root for license information. // Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. -use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; +use azure_core::{ + fmt::SafeDebug, + http::{pager::PagerOptions, poller::PollerOptions, ClientMethodOptions}, +}; /// Options to be passed to [`CertificateClient::backup_certificate()`](crate::generated::clients::CertificateClient::backup_certificate()) #[derive(Clone, Default, SafeDebug)] @@ -103,7 +106,7 @@ pub struct CertificateClientListCertificatePropertiesOptions<'a> { pub maxresults: Option, /// Allows customization of the method call. - pub method_options: ClientMethodOptions<'a>, + pub method_options: PagerOptions<'a>, } impl CertificateClientListCertificatePropertiesOptions<'_> { @@ -112,7 +115,7 @@ impl CertificateClientListCertificatePropertiesOptions<'_> { CertificateClientListCertificatePropertiesOptions { include_pending: self.include_pending, maxresults: self.maxresults, - method_options: ClientMethodOptions { + method_options: PagerOptions { context: self.method_options.context.into_owned(), }, } @@ -126,7 +129,7 @@ pub struct CertificateClientListCertificatePropertiesVersionsOptions<'a> { pub maxresults: Option, /// Allows customization of the method call. - pub method_options: ClientMethodOptions<'a>, + pub method_options: PagerOptions<'a>, } impl CertificateClientListCertificatePropertiesVersionsOptions<'_> { @@ -134,7 +137,7 @@ impl CertificateClientListCertificatePropertiesVersionsOptions<'_> { pub fn into_owned(self) -> CertificateClientListCertificatePropertiesVersionsOptions<'static> { CertificateClientListCertificatePropertiesVersionsOptions { maxresults: self.maxresults, - method_options: ClientMethodOptions { + method_options: PagerOptions { context: self.method_options.context.into_owned(), }, } @@ -151,7 +154,7 @@ pub struct CertificateClientListDeletedCertificatePropertiesOptions<'a> { pub maxresults: Option, /// Allows customization of the method call. - pub method_options: ClientMethodOptions<'a>, + pub method_options: PagerOptions<'a>, } impl CertificateClientListDeletedCertificatePropertiesOptions<'_> { @@ -160,7 +163,7 @@ impl CertificateClientListDeletedCertificatePropertiesOptions<'_> { CertificateClientListDeletedCertificatePropertiesOptions { include_pending: self.include_pending, maxresults: self.maxresults, - method_options: ClientMethodOptions { + method_options: PagerOptions { context: self.method_options.context.into_owned(), }, } @@ -174,7 +177,7 @@ pub struct CertificateClientListIssuerPropertiesOptions<'a> { pub maxresults: Option, /// Allows customization of the method call. - pub method_options: ClientMethodOptions<'a>, + pub method_options: PagerOptions<'a>, } impl CertificateClientListIssuerPropertiesOptions<'_> { @@ -182,7 +185,7 @@ impl CertificateClientListIssuerPropertiesOptions<'_> { pub fn into_owned(self) -> CertificateClientListIssuerPropertiesOptions<'static> { CertificateClientListIssuerPropertiesOptions { maxresults: self.maxresults, - method_options: ClientMethodOptions { + method_options: PagerOptions { context: self.method_options.context.into_owned(), }, } diff --git a/sdk/keyvault/azure_security_keyvault_keys/CHANGELOG.md b/sdk/keyvault/azure_security_keyvault_keys/CHANGELOG.md index 92f8204c60..015858c8cc 100644 --- a/sdk/keyvault/azure_security_keyvault_keys/CHANGELOG.md +++ b/sdk/keyvault/azure_security_keyvault_keys/CHANGELOG.md @@ -6,6 +6,10 @@ ### Breaking Changes +- `KeyClientListDeletedKeyPropertiesOptions::method_options` is now `PagerOptions`. +- `KeyClientListKeyPropertiesOptions::method_options` is now `PagerOptions`. +- `KeyClientListKeyPropertiesVersionsOptions::method_options` is now `PagerOptions`. + ### Bugs Fixed ### Other Changes diff --git a/sdk/keyvault/azure_security_keyvault_keys/src/generated/clients/key_client.rs b/sdk/keyvault/azure_security_keyvault_keys/src/generated/clients/key_client.rs index e877d618eb..b7c91ed5a3 100644 --- a/sdk/keyvault/azure_security_keyvault_keys/src/generated/clients/key_client.rs +++ b/sdk/keyvault/azure_security_keyvault_keys/src/generated/clients/key_client.rs @@ -686,51 +686,53 @@ impl KeyClient { .append_pair("maxresults", &maxresults.to_string()); } let api_version = self.api_version.clone(); - Ok(Pager::from_callback(move |next_link: PagerState| { - let url = match next_link { - PagerState::More(next_link) => { - let qp = next_link - .query_pairs() - .filter(|(name, _)| name.ne("api-version")); - let mut next_link = next_link.clone(); - next_link - .query_pairs_mut() - .clear() - .extend_pairs(qp) - .append_pair("api-version", &api_version); - next_link + Ok(Pager::from_callback( + move |next_link: PagerState, ctx| { + let url = match next_link { + PagerState::More(next_link) => { + let qp = next_link + .query_pairs() + .filter(|(name, _)| name.ne("api-version")); + let mut next_link = next_link.clone(); + next_link + .query_pairs_mut() + .clear() + .extend_pairs(qp) + .append_pair("api-version", &api_version); + next_link + } + PagerState::Initial => first_url.clone(), + }; + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let pipeline = pipeline.clone(); + async move { + let rsp = pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + let (status, headers, body) = rsp.deconstruct(); + let res: ListDeletedKeyPropertiesResult = json::from_json(&body)?; + let rsp = RawResponse::from_bytes(status, headers, body).into(); + Ok(match res.next_link { + Some(next_link) if !next_link.is_empty() => PagerResult::More { + response: rsp, + continuation: next_link.parse()?, + }, + _ => PagerResult::Done { response: rsp }, + }) } - PagerState::Initial => first_url.clone(), - }; - let mut request = Request::new(url, Method::Get); - request.insert_header("accept", "application/json"); - let ctx = options.method_options.context.clone(); - let pipeline = pipeline.clone(); - async move { - let rsp = pipeline - .send( - &ctx, - &mut request, - Some(PipelineSendOptions { - check_success: CheckSuccessOptions { - success_codes: &[200], - }, - ..Default::default() - }), - ) - .await?; - let (status, headers, body) = rsp.deconstruct(); - let res: ListDeletedKeyPropertiesResult = json::from_json(&body)?; - let rsp = RawResponse::from_bytes(status, headers, body).into(); - Ok(match res.next_link { - Some(next_link) if !next_link.is_empty() => PagerResult::More { - response: rsp, - continuation: next_link.parse()?, - }, - _ => PagerResult::Done { response: rsp }, - }) - } - })) + }, + Some(options.method_options), + )) } /// List keys in the specified vault. @@ -760,51 +762,53 @@ impl KeyClient { .append_pair("maxresults", &maxresults.to_string()); } let api_version = self.api_version.clone(); - Ok(Pager::from_callback(move |next_link: PagerState| { - let url = match next_link { - PagerState::More(next_link) => { - let qp = next_link - .query_pairs() - .filter(|(name, _)| name.ne("api-version")); - let mut next_link = next_link.clone(); - next_link - .query_pairs_mut() - .clear() - .extend_pairs(qp) - .append_pair("api-version", &api_version); - next_link + Ok(Pager::from_callback( + move |next_link: PagerState, ctx| { + let url = match next_link { + PagerState::More(next_link) => { + let qp = next_link + .query_pairs() + .filter(|(name, _)| name.ne("api-version")); + let mut next_link = next_link.clone(); + next_link + .query_pairs_mut() + .clear() + .extend_pairs(qp) + .append_pair("api-version", &api_version); + next_link + } + PagerState::Initial => first_url.clone(), + }; + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let pipeline = pipeline.clone(); + async move { + let rsp = pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + let (status, headers, body) = rsp.deconstruct(); + let res: ListKeyPropertiesResult = json::from_json(&body)?; + let rsp = RawResponse::from_bytes(status, headers, body).into(); + Ok(match res.next_link { + Some(next_link) if !next_link.is_empty() => PagerResult::More { + response: rsp, + continuation: next_link.parse()?, + }, + _ => PagerResult::Done { response: rsp }, + }) } - PagerState::Initial => first_url.clone(), - }; - let mut request = Request::new(url, Method::Get); - request.insert_header("accept", "application/json"); - let ctx = options.method_options.context.clone(); - let pipeline = pipeline.clone(); - async move { - let rsp = pipeline - .send( - &ctx, - &mut request, - Some(PipelineSendOptions { - check_success: CheckSuccessOptions { - success_codes: &[200], - }, - ..Default::default() - }), - ) - .await?; - let (status, headers, body) = rsp.deconstruct(); - let res: ListKeyPropertiesResult = json::from_json(&body)?; - let rsp = RawResponse::from_bytes(status, headers, body).into(); - Ok(match res.next_link { - Some(next_link) if !next_link.is_empty() => PagerResult::More { - response: rsp, - continuation: next_link.parse()?, - }, - _ => PagerResult::Done { response: rsp }, - }) - } - })) + }, + Some(options.method_options), + )) } /// Retrieves a list of individual key versions with the same key name. @@ -842,51 +846,53 @@ impl KeyClient { .append_pair("maxresults", &maxresults.to_string()); } let api_version = self.api_version.clone(); - Ok(Pager::from_callback(move |next_link: PagerState| { - let url = match next_link { - PagerState::More(next_link) => { - let qp = next_link - .query_pairs() - .filter(|(name, _)| name.ne("api-version")); - let mut next_link = next_link.clone(); - next_link - .query_pairs_mut() - .clear() - .extend_pairs(qp) - .append_pair("api-version", &api_version); - next_link + Ok(Pager::from_callback( + move |next_link: PagerState, ctx| { + let url = match next_link { + PagerState::More(next_link) => { + let qp = next_link + .query_pairs() + .filter(|(name, _)| name.ne("api-version")); + let mut next_link = next_link.clone(); + next_link + .query_pairs_mut() + .clear() + .extend_pairs(qp) + .append_pair("api-version", &api_version); + next_link + } + PagerState::Initial => first_url.clone(), + }; + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let pipeline = pipeline.clone(); + async move { + let rsp = pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + let (status, headers, body) = rsp.deconstruct(); + let res: ListKeyPropertiesResult = json::from_json(&body)?; + let rsp = RawResponse::from_bytes(status, headers, body).into(); + Ok(match res.next_link { + Some(next_link) if !next_link.is_empty() => PagerResult::More { + response: rsp, + continuation: next_link.parse()?, + }, + _ => PagerResult::Done { response: rsp }, + }) } - PagerState::Initial => first_url.clone(), - }; - let mut request = Request::new(url, Method::Get); - request.insert_header("accept", "application/json"); - let ctx = options.method_options.context.clone(); - let pipeline = pipeline.clone(); - async move { - let rsp = pipeline - .send( - &ctx, - &mut request, - Some(PipelineSendOptions { - check_success: CheckSuccessOptions { - success_codes: &[200], - }, - ..Default::default() - }), - ) - .await?; - let (status, headers, body) = rsp.deconstruct(); - let res: ListKeyPropertiesResult = json::from_json(&body)?; - let rsp = RawResponse::from_bytes(status, headers, body).into(); - Ok(match res.next_link { - Some(next_link) if !next_link.is_empty() => PagerResult::More { - response: rsp, - continuation: next_link.parse()?, - }, - _ => PagerResult::Done { response: rsp }, - }) - } - })) + }, + Some(options.method_options), + )) } /// Permanently deletes the specified key. diff --git a/sdk/keyvault/azure_security_keyvault_keys/src/generated/models/method_options.rs b/sdk/keyvault/azure_security_keyvault_keys/src/generated/models/method_options.rs index 213d5ac270..ee9ce03316 100644 --- a/sdk/keyvault/azure_security_keyvault_keys/src/generated/models/method_options.rs +++ b/sdk/keyvault/azure_security_keyvault_keys/src/generated/models/method_options.rs @@ -3,7 +3,10 @@ // Licensed under the MIT License. See License.txt in the project root for license information. // Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. -use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; +use azure_core::{ + fmt::SafeDebug, + http::{pager::PagerOptions, ClientMethodOptions}, +}; /// Options to be passed to [`KeyClient::backup_key()`](crate::generated::clients::KeyClient::backup_key()) #[derive(Clone, Default, SafeDebug)] @@ -103,7 +106,7 @@ pub struct KeyClientListDeletedKeyPropertiesOptions<'a> { pub maxresults: Option, /// Allows customization of the method call. - pub method_options: ClientMethodOptions<'a>, + pub method_options: PagerOptions<'a>, } impl KeyClientListDeletedKeyPropertiesOptions<'_> { @@ -111,7 +114,7 @@ impl KeyClientListDeletedKeyPropertiesOptions<'_> { pub fn into_owned(self) -> KeyClientListDeletedKeyPropertiesOptions<'static> { KeyClientListDeletedKeyPropertiesOptions { maxresults: self.maxresults, - method_options: ClientMethodOptions { + method_options: PagerOptions { context: self.method_options.context.into_owned(), }, } @@ -125,7 +128,7 @@ pub struct KeyClientListKeyPropertiesOptions<'a> { pub maxresults: Option, /// Allows customization of the method call. - pub method_options: ClientMethodOptions<'a>, + pub method_options: PagerOptions<'a>, } impl KeyClientListKeyPropertiesOptions<'_> { @@ -133,7 +136,7 @@ impl KeyClientListKeyPropertiesOptions<'_> { pub fn into_owned(self) -> KeyClientListKeyPropertiesOptions<'static> { KeyClientListKeyPropertiesOptions { maxresults: self.maxresults, - method_options: ClientMethodOptions { + method_options: PagerOptions { context: self.method_options.context.into_owned(), }, } @@ -147,7 +150,7 @@ pub struct KeyClientListKeyPropertiesVersionsOptions<'a> { pub maxresults: Option, /// Allows customization of the method call. - pub method_options: ClientMethodOptions<'a>, + pub method_options: PagerOptions<'a>, } impl KeyClientListKeyPropertiesVersionsOptions<'_> { @@ -155,7 +158,7 @@ impl KeyClientListKeyPropertiesVersionsOptions<'_> { pub fn into_owned(self) -> KeyClientListKeyPropertiesVersionsOptions<'static> { KeyClientListKeyPropertiesVersionsOptions { maxresults: self.maxresults, - method_options: ClientMethodOptions { + method_options: PagerOptions { context: self.method_options.context.into_owned(), }, } diff --git a/sdk/keyvault/azure_security_keyvault_secrets/CHANGELOG.md b/sdk/keyvault/azure_security_keyvault_secrets/CHANGELOG.md index de6602188d..04d8862c6d 100644 --- a/sdk/keyvault/azure_security_keyvault_secrets/CHANGELOG.md +++ b/sdk/keyvault/azure_security_keyvault_secrets/CHANGELOG.md @@ -6,6 +6,10 @@ ### Breaking Changes +- `SecretClientListDeletedSecretPropertiesOptions::method_options` is now `PagerOptions`. +- `SecretClientListSecretPropertiesOptions::method_options` is now `PagerOptions`. +- `SecretClientListSecretPropertiesVersionsOptions::method_options` is now `PagerOptions`. + ### Bugs Fixed ### Other Changes diff --git a/sdk/keyvault/azure_security_keyvault_secrets/src/generated/clients/secret_client.rs b/sdk/keyvault/azure_security_keyvault_secrets/src/generated/clients/secret_client.rs index 639d742627..3b77142b55 100644 --- a/sdk/keyvault/azure_security_keyvault_secrets/src/generated/clients/secret_client.rs +++ b/sdk/keyvault/azure_security_keyvault_secrets/src/generated/clients/secret_client.rs @@ -312,51 +312,53 @@ impl SecretClient { .append_pair("maxresults", &maxresults.to_string()); } let api_version = self.api_version.clone(); - Ok(Pager::from_callback(move |next_link: PagerState| { - let url = match next_link { - PagerState::More(next_link) => { - let qp = next_link - .query_pairs() - .filter(|(name, _)| name.ne("api-version")); - let mut next_link = next_link.clone(); - next_link - .query_pairs_mut() - .clear() - .extend_pairs(qp) - .append_pair("api-version", &api_version); - next_link + Ok(Pager::from_callback( + move |next_link: PagerState, ctx| { + let url = match next_link { + PagerState::More(next_link) => { + let qp = next_link + .query_pairs() + .filter(|(name, _)| name.ne("api-version")); + let mut next_link = next_link.clone(); + next_link + .query_pairs_mut() + .clear() + .extend_pairs(qp) + .append_pair("api-version", &api_version); + next_link + } + PagerState::Initial => first_url.clone(), + }; + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let pipeline = pipeline.clone(); + async move { + let rsp = pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + let (status, headers, body) = rsp.deconstruct(); + let res: ListDeletedSecretPropertiesResult = json::from_json(&body)?; + let rsp = RawResponse::from_bytes(status, headers, body).into(); + Ok(match res.next_link { + Some(next_link) if !next_link.is_empty() => PagerResult::More { + response: rsp, + continuation: next_link.parse()?, + }, + _ => PagerResult::Done { response: rsp }, + }) } - PagerState::Initial => first_url.clone(), - }; - let mut request = Request::new(url, Method::Get); - request.insert_header("accept", "application/json"); - let ctx = options.method_options.context.clone(); - let pipeline = pipeline.clone(); - async move { - let rsp = pipeline - .send( - &ctx, - &mut request, - Some(PipelineSendOptions { - check_success: CheckSuccessOptions { - success_codes: &[200], - }, - ..Default::default() - }), - ) - .await?; - let (status, headers, body) = rsp.deconstruct(); - let res: ListDeletedSecretPropertiesResult = json::from_json(&body)?; - let rsp = RawResponse::from_bytes(status, headers, body).into(); - Ok(match res.next_link { - Some(next_link) if !next_link.is_empty() => PagerResult::More { - response: rsp, - continuation: next_link.parse()?, - }, - _ => PagerResult::Done { response: rsp }, - }) - } - })) + }, + Some(options.method_options), + )) } /// List secrets in a specified key vault. @@ -386,51 +388,53 @@ impl SecretClient { .append_pair("maxresults", &maxresults.to_string()); } let api_version = self.api_version.clone(); - Ok(Pager::from_callback(move |next_link: PagerState| { - let url = match next_link { - PagerState::More(next_link) => { - let qp = next_link - .query_pairs() - .filter(|(name, _)| name.ne("api-version")); - let mut next_link = next_link.clone(); - next_link - .query_pairs_mut() - .clear() - .extend_pairs(qp) - .append_pair("api-version", &api_version); - next_link + Ok(Pager::from_callback( + move |next_link: PagerState, ctx| { + let url = match next_link { + PagerState::More(next_link) => { + let qp = next_link + .query_pairs() + .filter(|(name, _)| name.ne("api-version")); + let mut next_link = next_link.clone(); + next_link + .query_pairs_mut() + .clear() + .extend_pairs(qp) + .append_pair("api-version", &api_version); + next_link + } + PagerState::Initial => first_url.clone(), + }; + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let pipeline = pipeline.clone(); + async move { + let rsp = pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + let (status, headers, body) = rsp.deconstruct(); + let res: ListSecretPropertiesResult = json::from_json(&body)?; + let rsp = RawResponse::from_bytes(status, headers, body).into(); + Ok(match res.next_link { + Some(next_link) if !next_link.is_empty() => PagerResult::More { + response: rsp, + continuation: next_link.parse()?, + }, + _ => PagerResult::Done { response: rsp }, + }) } - PagerState::Initial => first_url.clone(), - }; - let mut request = Request::new(url, Method::Get); - request.insert_header("accept", "application/json"); - let ctx = options.method_options.context.clone(); - let pipeline = pipeline.clone(); - async move { - let rsp = pipeline - .send( - &ctx, - &mut request, - Some(PipelineSendOptions { - check_success: CheckSuccessOptions { - success_codes: &[200], - }, - ..Default::default() - }), - ) - .await?; - let (status, headers, body) = rsp.deconstruct(); - let res: ListSecretPropertiesResult = json::from_json(&body)?; - let rsp = RawResponse::from_bytes(status, headers, body).into(); - Ok(match res.next_link { - Some(next_link) if !next_link.is_empty() => PagerResult::More { - response: rsp, - continuation: next_link.parse()?, - }, - _ => PagerResult::Done { response: rsp }, - }) - } - })) + }, + Some(options.method_options), + )) } /// List all versions of the specified secret. @@ -469,51 +473,53 @@ impl SecretClient { .append_pair("maxresults", &maxresults.to_string()); } let api_version = self.api_version.clone(); - Ok(Pager::from_callback(move |next_link: PagerState| { - let url = match next_link { - PagerState::More(next_link) => { - let qp = next_link - .query_pairs() - .filter(|(name, _)| name.ne("api-version")); - let mut next_link = next_link.clone(); - next_link - .query_pairs_mut() - .clear() - .extend_pairs(qp) - .append_pair("api-version", &api_version); - next_link + Ok(Pager::from_callback( + move |next_link: PagerState, ctx| { + let url = match next_link { + PagerState::More(next_link) => { + let qp = next_link + .query_pairs() + .filter(|(name, _)| name.ne("api-version")); + let mut next_link = next_link.clone(); + next_link + .query_pairs_mut() + .clear() + .extend_pairs(qp) + .append_pair("api-version", &api_version); + next_link + } + PagerState::Initial => first_url.clone(), + }; + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let pipeline = pipeline.clone(); + async move { + let rsp = pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + let (status, headers, body) = rsp.deconstruct(); + let res: ListSecretPropertiesResult = json::from_json(&body)?; + let rsp = RawResponse::from_bytes(status, headers, body).into(); + Ok(match res.next_link { + Some(next_link) if !next_link.is_empty() => PagerResult::More { + response: rsp, + continuation: next_link.parse()?, + }, + _ => PagerResult::Done { response: rsp }, + }) } - PagerState::Initial => first_url.clone(), - }; - let mut request = Request::new(url, Method::Get); - request.insert_header("accept", "application/json"); - let ctx = options.method_options.context.clone(); - let pipeline = pipeline.clone(); - async move { - let rsp = pipeline - .send( - &ctx, - &mut request, - Some(PipelineSendOptions { - check_success: CheckSuccessOptions { - success_codes: &[200], - }, - ..Default::default() - }), - ) - .await?; - let (status, headers, body) = rsp.deconstruct(); - let res: ListSecretPropertiesResult = json::from_json(&body)?; - let rsp = RawResponse::from_bytes(status, headers, body).into(); - Ok(match res.next_link { - Some(next_link) if !next_link.is_empty() => PagerResult::More { - response: rsp, - continuation: next_link.parse()?, - }, - _ => PagerResult::Done { response: rsp }, - }) - } - })) + }, + Some(options.method_options), + )) } /// Permanently deletes the specified secret. diff --git a/sdk/keyvault/azure_security_keyvault_secrets/src/generated/models/method_options.rs b/sdk/keyvault/azure_security_keyvault_secrets/src/generated/models/method_options.rs index ae3a897934..fe100234af 100644 --- a/sdk/keyvault/azure_security_keyvault_secrets/src/generated/models/method_options.rs +++ b/sdk/keyvault/azure_security_keyvault_secrets/src/generated/models/method_options.rs @@ -4,7 +4,10 @@ // Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. use super::ContentType; -use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; +use azure_core::{ + fmt::SafeDebug, + http::{pager::PagerOptions, ClientMethodOptions}, +}; /// Options to be passed to [`SecretClient::backup_secret()`](crate::generated::clients::SecretClient::backup_secret()) #[derive(Clone, Default, SafeDebug)] @@ -48,8 +51,8 @@ pub struct SecretClientListDeletedSecretPropertiesOptions<'a> { /// Maximum number of results to return in a page. If not specified the service will return up to 25 results. pub maxresults: Option, - /// Allows customization of the method call. - pub method_options: ClientMethodOptions<'a>, + /// Allows customization of the pager. + pub method_options: PagerOptions<'a>, } impl SecretClientListDeletedSecretPropertiesOptions<'_> { @@ -57,7 +60,7 @@ impl SecretClientListDeletedSecretPropertiesOptions<'_> { pub fn into_owned(self) -> SecretClientListDeletedSecretPropertiesOptions<'static> { SecretClientListDeletedSecretPropertiesOptions { maxresults: self.maxresults, - method_options: ClientMethodOptions { + method_options: PagerOptions { context: self.method_options.context.into_owned(), }, } @@ -70,8 +73,8 @@ pub struct SecretClientListSecretPropertiesOptions<'a> { /// Maximum number of results to return in a page. If not specified the service will return up to 25 results. pub maxresults: Option, - /// Allows customization of the method call. - pub method_options: ClientMethodOptions<'a>, + /// Allows customization of the pager. + pub method_options: PagerOptions<'a>, } impl SecretClientListSecretPropertiesOptions<'_> { @@ -79,7 +82,7 @@ impl SecretClientListSecretPropertiesOptions<'_> { pub fn into_owned(self) -> SecretClientListSecretPropertiesOptions<'static> { SecretClientListSecretPropertiesOptions { maxresults: self.maxresults, - method_options: ClientMethodOptions { + method_options: PagerOptions { context: self.method_options.context.into_owned(), }, } @@ -92,8 +95,8 @@ pub struct SecretClientListSecretPropertiesVersionsOptions<'a> { /// Maximum number of results to return in a page. If not specified the service will return up to 25 results. pub maxresults: Option, - /// Allows customization of the method call. - pub method_options: ClientMethodOptions<'a>, + /// Allows customization of the pager. + pub method_options: PagerOptions<'a>, } impl SecretClientListSecretPropertiesVersionsOptions<'_> { @@ -101,7 +104,7 @@ impl SecretClientListSecretPropertiesVersionsOptions<'_> { pub fn into_owned(self) -> SecretClientListSecretPropertiesVersionsOptions<'static> { SecretClientListSecretPropertiesVersionsOptions { maxresults: self.maxresults, - method_options: ClientMethodOptions { + method_options: PagerOptions { context: self.method_options.context.into_owned(), }, } diff --git a/sdk/storage/azure_storage_blob/CHANGELOG.md b/sdk/storage/azure_storage_blob/CHANGELOG.md index c2a196ab1d..dcfefb1128 100644 --- a/sdk/storage/azure_storage_blob/CHANGELOG.md +++ b/sdk/storage/azure_storage_blob/CHANGELOG.md @@ -14,6 +14,11 @@ ### Breaking Changes +- Changed the following options structs' `method_options` from `ClientMethodOptions` to `PagerOptions`: + - `BlobContainerClientListBlobFlatSegmentOptions` + - `BlobContainerClientListBlobHierarchySegmentOptions` + - `BlobServiceClientListContainersSegmentOptions` + - Removed the `container_name()` and `blob_name()` accessors on relevant clients. - Removed the `endpoint` struct field on all clients, as this value is now returned directly from the underlying generated client. - Changed the `container_name` and `blob_name` parameters from owned `String` to `&str` reference on relevant client constructor methods (`new()`). diff --git a/sdk/storage/azure_storage_blob/src/generated/clients/blob_container_client.rs b/sdk/storage/azure_storage_blob/src/generated/clients/blob_container_client.rs index 455159d393..6580945933 100644 --- a/sdk/storage/azure_storage_blob/src/generated/clients/blob_container_client.rs +++ b/sdk/storage/azure_storage_blob/src/generated/clients/blob_container_client.rs @@ -28,8 +28,8 @@ use azure_core::{ http::{ pager::{PagerResult, PagerState}, policies::{BearerTokenAuthorizationPolicy, Policy}, - ClientOptions, Method, NoFormat, PageIterator, Pipeline, PipelineSendOptions, RawResponse, - Request, RequestContent, Response, Url, XmlFormat, + ClientOptions, Context, Method, NoFormat, PageIterator, Pipeline, PipelineSendOptions, + RawResponse, Request, RequestContent, Response, Url, XmlFormat, }, time::to_rfc7231, tracing, xml, Result, @@ -837,7 +837,7 @@ impl BlobContainerClient { } let version = self.version.clone(); Ok(PageIterator::from_callback( - move |marker: PagerState| { + move |marker: PagerState, ctx| { let mut url = first_url.clone(); if let PagerState::More(marker) = marker { if url.query_pairs().any(|(name, _)| name.eq("marker")) { @@ -857,7 +857,6 @@ impl BlobContainerClient { request.insert_header("x-ms-client-request-id", client_request_id); } request.insert_header("x-ms-version", &version); - let ctx = options.method_options.context.clone(); let pipeline = pipeline.clone(); async move { let rsp = pipeline @@ -884,6 +883,7 @@ impl BlobContainerClient { }) } }, + Some(options.method_options), )) } @@ -964,7 +964,7 @@ impl BlobContainerClient { } let version = self.version.clone(); Ok(PageIterator::from_callback( - move |marker: PagerState| { + move |marker: PagerState, ctx| { let mut url = first_url.clone(); if let PagerState::More(marker) = marker { if url.query_pairs().any(|(name, _)| name.eq("marker")) { @@ -984,7 +984,6 @@ impl BlobContainerClient { request.insert_header("x-ms-client-request-id", client_request_id); } request.insert_header("x-ms-version", &version); - let ctx = options.method_options.context.clone(); let pipeline = pipeline.clone(); async move { let rsp = pipeline @@ -1011,6 +1010,7 @@ impl BlobContainerClient { }) } }, + Some(options.method_options), )) } diff --git a/sdk/storage/azure_storage_blob/src/generated/clients/blob_service_client.rs b/sdk/storage/azure_storage_blob/src/generated/clients/blob_service_client.rs index 27278e50ba..f9a3e8a6b3 100644 --- a/sdk/storage/azure_storage_blob/src/generated/clients/blob_service_client.rs +++ b/sdk/storage/azure_storage_blob/src/generated/clients/blob_service_client.rs @@ -18,8 +18,8 @@ use azure_core::{ http::{ pager::{PagerResult, PagerState}, policies::{BearerTokenAuthorizationPolicy, Policy}, - ClientOptions, Method, NoFormat, PageIterator, Pipeline, PipelineSendOptions, RawResponse, - Request, RequestContent, Response, Url, XmlFormat, + ClientOptions, Context, Method, NoFormat, PageIterator, Pipeline, PipelineSendOptions, + RawResponse, Request, RequestContent, Response, Url, XmlFormat, }, tracing, xml, Result, }; @@ -445,7 +445,7 @@ impl BlobServiceClient { } let version = self.version.clone(); Ok(PageIterator::from_callback( - move |marker: PagerState| { + move |marker: PagerState, ctx| { let mut url = first_url.clone(); if let PagerState::More(marker) = marker { if url.query_pairs().any(|(name, _)| name.eq("marker")) { @@ -465,7 +465,6 @@ impl BlobServiceClient { request.insert_header("x-ms-client-request-id", client_request_id); } request.insert_header("x-ms-version", &version); - let ctx = options.method_options.context.clone(); let pipeline = pipeline.clone(); async move { let rsp = pipeline @@ -492,6 +491,7 @@ impl BlobServiceClient { }) } }, + Some(options.method_options), )) } diff --git a/sdk/storage/azure_storage_blob/src/generated/models/method_options.rs b/sdk/storage/azure_storage_blob/src/generated/models/method_options.rs index 3115d42fb7..28a73a3d8e 100644 --- a/sdk/storage/azure_storage_blob/src/generated/models/method_options.rs +++ b/sdk/storage/azure_storage_blob/src/generated/models/method_options.rs @@ -9,7 +9,11 @@ use super::{ ListBlobsIncludeItem, ListContainersIncludeType, PremiumPageBlobAccessTier, PublicAccessType, RehydratePriority, }; -use azure_core::{fmt::SafeDebug, http::ClientMethodOptions, time::OffsetDateTime}; +use azure_core::{ + fmt::SafeDebug, + http::{pager::PagerOptions, ClientMethodOptions}, + time::OffsetDateTime, +}; use std::collections::HashMap; /// Options to be passed to `AppendBlobClient::append_block()` @@ -1333,7 +1337,7 @@ pub struct BlobContainerClientListBlobFlatSegmentOptions<'a> { pub maxresults: Option, /// Allows customization of the method call. - pub method_options: ClientMethodOptions<'a>, + pub method_options: PagerOptions<'a>, /// Filters the results to return only containers whose name begins with the specified prefix. pub prefix: Option, @@ -1350,7 +1354,7 @@ impl BlobContainerClientListBlobFlatSegmentOptions<'_> { include: self.include, marker: self.marker, maxresults: self.maxresults, - method_options: ClientMethodOptions { + method_options: PagerOptions { context: self.method_options.context.into_owned(), }, prefix: self.prefix, @@ -1379,7 +1383,7 @@ pub struct BlobContainerClientListBlobHierarchySegmentOptions<'a> { pub maxresults: Option, /// Allows customization of the method call. - pub method_options: ClientMethodOptions<'a>, + pub method_options: PagerOptions<'a>, /// Filters the results to return only containers whose name begins with the specified prefix. pub prefix: Option, @@ -1396,7 +1400,7 @@ impl BlobContainerClientListBlobHierarchySegmentOptions<'_> { include: self.include, marker: self.marker, maxresults: self.maxresults, - method_options: ClientMethodOptions { + method_options: PagerOptions { context: self.method_options.context.into_owned(), }, prefix: self.prefix, @@ -1620,7 +1624,7 @@ pub struct BlobServiceClientListContainersSegmentOptions<'a> { pub maxresults: Option, /// Allows customization of the method call. - pub method_options: ClientMethodOptions<'a>, + pub method_options: PagerOptions<'a>, /// Filters the results to return only containers whose name begins with the specified prefix. pub prefix: Option, @@ -1637,7 +1641,7 @@ impl BlobServiceClientListContainersSegmentOptions<'_> { include: self.include, marker: self.marker, maxresults: self.maxresults, - method_options: ClientMethodOptions { + method_options: PagerOptions { context: self.method_options.context.into_owned(), }, prefix: self.prefix, diff --git a/sdk/storage/azure_storage_queue/CHANGELOG.md b/sdk/storage/azure_storage_queue/CHANGELOG.md index 0d6b04c7b7..b9ac3daf28 100644 --- a/sdk/storage/azure_storage_queue/CHANGELOG.md +++ b/sdk/storage/azure_storage_queue/CHANGELOG.md @@ -6,6 +6,8 @@ ### Breaking Changes +- Changed `QueueServiceClientListQueuesOptions::method_options` from `ClientMethodOptions` to `PagerOptions` + ### Bugs Fixed ### Other Changes @@ -14,4 +16,4 @@ ### Features Added -* Initial supported release. +- Initial supported release. diff --git a/sdk/storage/azure_storage_queue/src/generated/clients/queue_service_client.rs b/sdk/storage/azure_storage_queue/src/generated/clients/queue_service_client.rs index f4d442dba6..07685b92cc 100644 --- a/sdk/storage/azure_storage_queue/src/generated/clients/queue_service_client.rs +++ b/sdk/storage/azure_storage_queue/src/generated/clients/queue_service_client.rs @@ -255,7 +255,7 @@ impl QueueServiceClient { } let version = self.version.clone(); Ok(PageIterator::from_callback( - move |marker: PagerState| { + move |marker: PagerState, ctx| { let mut url = first_url.clone(); if let PagerState::More(marker) = marker { if url.query_pairs().any(|(name, _)| name.eq("marker")) { @@ -275,7 +275,6 @@ impl QueueServiceClient { request.insert_header("x-ms-client-request-id", client_request_id); } request.insert_header("x-ms-version", &version); - let ctx = options.method_options.context.clone(); let pipeline = pipeline.clone(); async move { let rsp = pipeline @@ -302,6 +301,7 @@ impl QueueServiceClient { }) } }, + Some(options.method_options), )) } diff --git a/sdk/storage/azure_storage_queue/src/generated/models/method_options.rs b/sdk/storage/azure_storage_queue/src/generated/models/method_options.rs index 8c9389356e..0668ccb1ab 100644 --- a/sdk/storage/azure_storage_queue/src/generated/models/method_options.rs +++ b/sdk/storage/azure_storage_queue/src/generated/models/method_options.rs @@ -6,7 +6,7 @@ use super::{ListQueuesIncludeType, QueueMessage}; use azure_core::{ fmt::SafeDebug, - http::{ClientMethodOptions, RequestContent, XmlFormat}, + http::{pager::PagerOptions, ClientMethodOptions, RequestContent, XmlFormat}, }; use std::collections::HashMap; @@ -237,7 +237,7 @@ pub struct QueueServiceClientListQueuesOptions<'a> { pub maxresults: Option, /// Allows customization of the method call. - pub method_options: ClientMethodOptions<'a>, + pub method_options: PagerOptions<'a>, /// Filters the results to return only queues whose name begins with the specified prefix. pub prefix: Option, @@ -254,7 +254,7 @@ impl QueueServiceClientListQueuesOptions<'_> { include: self.include, marker: self.marker, maxresults: self.maxresults, - method_options: ClientMethodOptions { + method_options: PagerOptions { context: self.method_options.context.into_owned(), }, prefix: self.prefix,