midiserde 0.1.1

When mini isn't enough and serde is too much
Documentation
//! Conversion between Rust types and `miniserde::json::Value`.
//!
//! Miniserde doesn't provide `from_value` or `to_value` out of the box. This module fills that gap.
//!
//! # Two-stage deserialization
//!
//! Sometimes you need to parse JSON into an untyped `Value` first, then deserialize
//! to a concrete type. For example:
//!
//! - **Extra fields capture**: Store unknown JSON fields as `Value`, then deserialize
//!   to a known type when you have more context (e.g. a discriminator).
//! - **Polymorphic buffers**: When the discriminator isn't first in the JSON, buffer
//!   the whole object as `Value`, then replay into the correct type once known.
//! - **Conditional deserialization**: Inspect or transform the `Value` before
//!   committing to a specific Rust type.
//!
//! # Example
//!
//! ```
//! use midiserde::{json, Deserialize, from_value};
//!
//! #[derive(Deserialize)]
//! struct Dog {
//!     name: String,
//!     breed: String,
//! }
//!
//! // Stage 1: Parse JSON string → Value
//! let json_str = r#"{"name": "Rex", "breed": "Golden Retriever"}"#;
//! let value: miniserde::json::Value = json::from_str(json_str)?;
//!
//! // Stage 2: Deserialize Value → concrete type
//! let dog: Dog = from_value(&value)?;
//! assert_eq!(dog.name, "Rex");
//! # Ok::<(), miniserde::Error>(())
//! ```

use miniserde::de::Visitor;
use miniserde::json::{Array, Number, Object, Value};
use miniserde::ser::Fragment;
use miniserde::{Deserialize, Error, Result, Serialize};

/// Replay a captured `Value` to a Visitor.
///
/// This effectively "deserializes" the `Value` into whatever the Visitor expects.
/// The Visitor receives the same call sequence it would get from the normal JSON
/// deserializer.
pub fn replay_value_to_visitor(value: &Value, visitor: &mut dyn Visitor) -> Result<()> {
    match value {
        Value::Null => visitor.null(),
        Value::Bool(b) => visitor.boolean(*b),
        Value::String(s) => visitor.string(s),
        Value::Number(n) => match n {
            Number::U64(n) => visitor.nonnegative(*n),
            Number::I64(n) => visitor.negative(*n),
            Number::F64(n) => visitor.float(*n),
        },
        Value::Array(arr) => {
            let mut seq = visitor.seq()?;
            for item in arr.iter() {
                let element_visitor = seq.element()?;
                replay_value_to_visitor(item, element_visitor)?;
            }
            seq.finish()
        }
        Value::Object(obj) => {
            let mut map = visitor.map()?;
            for (k, v) in obj.iter() {
                let field_visitor = map.key(k)?;
                replay_value_to_visitor(v, field_visitor)?;
            }
            map.finish()
        }
    }
}

/// Deserialize a type from a `miniserde::json::Value`.
///
/// This is the miniserde equivalent of `serde_json::from_value`.
///
/// # Example
///
/// ```
/// use midiserde::{json, Deserialize, from_value};
///
/// #[derive(Deserialize)]
/// struct Config {
///     name: String,
///     port: u16,
/// }
///
/// let value: miniserde::json::Value = json::from_str(r#"{"name": "api", "port": 8080}"#)?;
/// let config: Config = from_value(&value)?;
/// # Ok::<(), miniserde::Error>(())
/// ```
pub fn from_value<T: Deserialize>(value: &Value) -> Result<T> {
    let mut out: Option<T> = None;
    let visitor = T::begin(&mut out);
    replay_value_to_visitor(value, visitor)?;
    out.ok_or(Error)
}

/// Serialize a type into a `miniserde::json::Value`.
///
/// This is the miniserde equivalent of `serde_json::to_value`.
///
/// # Example
///
/// ```
/// use midiserde::{json, Serialize, to_value};
///
/// #[derive(Serialize)]
/// struct Config {
///     name: String,
///     port: u16,
/// }
///
/// let config = Config { name: "api".into(), port: 8080 };
/// let value = to_value(&config);
/// // Round-trip: Value → JSON string → compare
/// assert_eq!(json::to_string(&value), r#"{"name":"api","port":8080}"#);
/// ```
pub fn to_value<T: Serialize>(value: &T) -> Value {
    fragment_to_value(value.begin())
}

/// Convert a `miniserde::ser::Fragment` to a `miniserde::json::Value`.
///
/// This is the miniserde equivalent of `serde_json::to_value`.
///
/// # Example
///
/// ```
/// use midiserde::{json, Serialize, to_value};
/// 
/// #[derive(Serialize)]
/// struct Config {
///     name: String,
///     port: u16,
/// }
/// 
/// let config = Config { name: "api".into(), port: 8080 };
/// let value = to_value(&config);
/// assert_eq!(json::to_string(&value), r#"{"name":"api","port":8080}"#);
/// ```
fn fragment_to_value(fragment: Fragment<'_>) -> Value {
    match fragment {
        Fragment::Null => Value::Null,
        Fragment::Bool(b) => Value::Bool(b),
        Fragment::Str(s) => Value::String(s.into_owned()),
        Fragment::U64(n) => Value::Number(Number::U64(n)),
        Fragment::I64(n) => Value::Number(Number::I64(n)),
        Fragment::F64(n) => Value::Number(Number::F64(n)),
        Fragment::Seq(mut seq) => {
            let mut arr = Array::new();
            while let Some(elem) = seq.next() {
                arr.push(fragment_to_value(elem.begin()));
            }
            Value::Array(arr)
        }
        Fragment::Map(mut map) => {
            let mut obj = Object::new();
            while let Some((k, v)) = map.next() {
                obj.insert(k.into_owned(), fragment_to_value(v.begin()));
            }
            Value::Object(obj)
        }
    }
}