use crate::{SdkError, cbor, sealed::Sealed, types::authorization::private::QueryElementOrResponseItem, wit};
use serde::Deserialize;
use super::QueryElementId;
#[derive(Clone, Copy)]
pub struct ResponseElements<'a>(&'a wit::ResponseElements);
impl<'a> From<&'a wit::ResponseElements> for ResponseElements<'a> {
fn from(value: &'a wit::ResponseElements) -> Self {
Self(value)
}
}
#[allow(clippy::len_without_is_empty)]
impl<'a> ResponseElements<'a> {
pub fn len(&self) -> usize {
self.0.elements.len()
}
pub fn iter(&self) -> impl ExactSizeIterator<Item = ResponseElement<'a>> + 'a {
(*self).into_iter()
}
pub fn iter_grouped_by_directive_name(
&self,
) -> impl ExactSizeIterator<Item = (&'a str, impl ExactSizeIterator<Item = ResponseElement<'a>> + 'a)> + 'a {
let resp = self.0;
let items = &resp.items;
self.0.directive_names.iter().map(move |(name, start, end)| {
let start = *start;
(
name.as_str(),
resp.elements[start as usize..*end as usize]
.iter()
.map(move |inner| ResponseElement {
items,
query_element_id: QueryElementId(inner.query_element_id),
items_range: inner.items_range,
}),
)
})
}
}
impl<'a> IntoIterator for ResponseElements<'a> {
type Item = ResponseElement<'a>;
type IntoIter = ResponseElementsIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
ResponseElementsIterator {
items: &self.0.items,
iter: self.0.elements.iter(),
}
}
}
pub struct ResponseElementsIterator<'a> {
items: &'a [Vec<u8>],
iter: std::slice::Iter<'a, wit::ResponseElement>,
}
impl ExactSizeIterator for ResponseElementsIterator<'_> {}
impl<'a> Iterator for ResponseElementsIterator<'a> {
type Item = ResponseElement<'a>;
fn next(&mut self) -> Option<Self::Item> {
let items = self.items;
self.iter.next().map(move |inner| ResponseElement {
items,
query_element_id: QueryElementId(inner.query_element_id),
items_range: inner.items_range,
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
#[derive(Clone, Copy)]
pub struct ResponseElement<'a> {
items: &'a [Vec<u8>],
query_element_id: QueryElementId,
items_range: (u32, u32),
}
impl<'a> ResponseElement<'a> {
pub fn query_element_id(&self) -> QueryElementId {
self.query_element_id
}
pub fn items(&self) -> impl ExactSizeIterator<Item = ResponseItem<'a>> {
let (start, end) = self.items_range;
self.items[start as usize..end as usize]
.iter()
.enumerate()
.map(move |(offset, bytes)| ResponseItem {
bytes,
ix: start + offset as u32,
})
}
}
impl Sealed for ResponseItem<'_> {}
impl QueryElementOrResponseItem for ResponseItem<'_> {
fn ix(&self) -> u32 {
self.ix
}
}
pub struct ResponseItem<'a> {
bytes: &'a [u8],
pub(in crate::types) ix: u32,
}
impl<'a> ResponseItem<'a> {
pub fn directive_arguments<T>(&self) -> Result<T, SdkError>
where
T: Deserialize<'a>,
{
cbor::from_slice(self.bytes).map_err(Into::into)
}
}