Skip to main content

netget/client/
wire_values.rs

1//! Checked conversion of JSON action values to protocol fields.
2
3use anyhow::{Context, Result};
4use serde_json::Value;
5
6/// Preserve an absent/null optional field's default; reject malformed or overflowing values.
7pub fn number<T: TryFrom<u64> + Copy>(data: &Value, key: &str, default: T) -> Result<T> {
8    match data.get(key) {
9        None | Some(Value::Null) => Ok(default),
10        Some(value) => {
11            let raw = value
12                .as_u64()
13                .with_context(|| format!("'{key}' must be an unsigned integer"))?;
14            T::try_from(raw)
15                .map_err(|_| anyhow::anyhow!("'{key}' value {raw} exceeds its wire field"))
16        }
17    }
18}
19
20/// A wire byte array cannot silently omit invalid elements or wrap values modulo 256.
21pub fn bytes(values: &[Value]) -> Result<Vec<u8>> {
22    values
23        .iter()
24        .enumerate()
25        .map(|(index, value)| {
26            value
27                .as_u64()
28                .and_then(|value| u8::try_from(value).ok())
29                .with_context(|| {
30                    format!("byte array element {index} must be an integer in 0..=255")
31                })
32        })
33        .collect()
34}