armour-core 0.2.0

Core types for armour ecosystem
Documentation
//! Leak-based `Deserialize` impls for [`KeyScheme`] and related armour-core types.
//!
//! [`Typ`] deserialization lives in `armour-typ` (orphan-rule requirement after
//! schema types moved to that crate). Enable via the `deserialize` feature on
//! either crate.
//!
//! # Warning
//!
//! Every call to `deserialize` leaks memory proportional to the size of the
//! decoded schema (strings and field arrays become `&'static` via [`Box::leak`]).
//! Safe for CLI tools and short-lived clients that deserialize a bounded set
//! of schemas per process. **Do not use in long-running servers that parse
//! untrusted or unbounded JSON schemas.**

use serde::Deserialize;

use crate::key_type::{KeyScheme, KeyType};

fn leak_slice<T>(v: Vec<T>) -> &'static [T] {
    Box::leak(v.into_boxed_slice())
}

// --- KeyScheme / KeyType ---
//
// `KeyType` already derives `Deserialize` (it is `Copy` with no borrowed data).
// `KeyScheme::Typed(&'static [KeyType])` needs a manual impl that leaks the
// parsed `Vec<KeyType>` into a `'static` slice.

#[derive(Deserialize)]
#[serde(tag = "type", content = "data")]
enum KeySchemeWire {
    Typed(Vec<KeyType>),
    Bytes,
}

impl<'de> Deserialize<'de> for KeyScheme {
    fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        let w = KeySchemeWire::deserialize(d)?;
        Ok(match w {
            KeySchemeWire::Typed(v) => KeyScheme::Typed(leak_slice(v)),
            KeySchemeWire::Bytes => KeyScheme::Bytes,
        })
    }
}