midiserde 0.1.1

When mini isn't enough and serde is too much
Documentation
//! Tests for custom `#[mini(with = "...")]` implementations.
//!
//! Run: `cargo test -p midiserde --features full custom_with`

use midiserde::{json, Deserialize, Serialize};

mod string_as_f64 {
    use miniserde::de::Visitor;
    use miniserde::ser::Fragment;

    pub fn begin(out: &mut Option<f64>) -> &mut dyn Visitor {
        Place::new(out)
    }

    pub fn serialize(value: &f64) -> Fragment<'_> {
        Fragment::Str(std::borrow::Cow::Owned(value.to_string()))
    }

    #[repr(C)]
    struct Place {
        out: Option<f64>,
    }

    impl Place {
        fn new(out: &mut Option<f64>) -> &mut Self {
            unsafe { &mut *std::ptr::addr_of_mut!(*out).cast::<Place>() }
        }
    }

    impl Visitor for Place {
        fn string(&mut self, s: &str) -> miniserde::Result<()> {
            let val: f64 = s.parse().map_err(|_| miniserde::Error)?;
            self.out = Some(val);
            Ok(())
        }
    }
}

#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct Quote {
    symbol: String,
    #[mini(with = "string_as_f64")]
    price: f64,
}

#[test]
fn deserialize() {
    let j = r#"{"symbol": "AAPL", "price": "182.63"}"#;
    let v: Quote = json::from_str(j).unwrap();
    assert_eq!(v.symbol, "AAPL");
    assert!((v.price - 182.63).abs() < f64::EPSILON);
}

#[test]
fn serialize() {
    let v = Quote {
        symbol: "AAPL".into(),
        price: 182.63,
    };
    let j = json::to_string(&v);
    assert!(j.contains(r#""price":"182.63""#));
}

#[test]
fn roundtrip() {
    let original = Quote {
        symbol: "GOOG".into(),
        price: 2800.5,
    };
    let j = json::to_string(&original);
    let parsed: Quote = json::from_str(&j).unwrap();
    assert_eq!(original, parsed);
}

/// Invalid f64 string returns Err, does not panic.
#[test]
fn invalid_f64_string() {
    let j = r#"{"symbol": "AAPL", "price": "not-a-number"}"#;
    let result: Result<Quote, _> = json::from_str(j);
    assert!(result.is_err());
}