tarantool_rs/utils/
deser.rs

1use rmpv::Value;
2use serde::de::DeserializeOwned;
3
4use crate::{codec::consts::keys, errors::DecodingError};
5
6pub fn value_to_map(value: Value) -> Result<Vec<(Value, Value)>, DecodingError> {
7    match value {
8        Value::Map(x) => Ok(x),
9        rest => Err(DecodingError::type_mismatch("map", rest.to_string())),
10    }
11}
12
13pub(crate) fn find_and_take_single_key_in_map(key: u8, map: Vec<(Value, Value)>) -> Option<Value> {
14    for (k, v) in map {
15        if matches!(k, Value::Integer(x) if x.as_u64().map_or(false, |y| y == key as u64)) {
16            return Some(v);
17        }
18    }
19    None
20}
21
22/// Extract IPROTO_DATA from response body and deserialize it.
23pub fn extract_iproto_data(value: Value) -> Result<Value, DecodingError> {
24    let map = value_to_map(value).map_err(|err| err.in_other("OK response body"))?;
25    find_and_take_single_key_in_map(keys::DATA, map)
26        .ok_or_else(|| DecodingError::missing_key("DATA").in_other("OK response body"))
27}
28
29/// Extract IPROTO_DATA from response body and deserialize it into provided type.
30pub fn extract_and_deserialize_iproto_data<T: DeserializeOwned>(
31    value: Value,
32) -> Result<T, DecodingError> {
33    extract_iproto_data(value).and_then(|x| rmpv::ext::from_value(x).map_err(Into::into))
34}