ic-platform 0.29.1

Controlled Candid and IC runtime dependency boundary
Documentation
use super::*;
use crate::candid_codec::{
    decoder::{Limits, decode_one},
    encode_one,
};

#[test]
fn natural_range_wire_and_serde_match_registry() {
    let limits = Limits {
        bytes: 8192,
        header: 1024,
        types: 32,
        work: 100_000,
        allocation: 32_768,
    };
    for bits in [0usize, 1, 7, 32, 64, 128, 256, 1024, 8192] {
        let value = BigUint::from(1u8) << bits;
        for magnitude in [value.clone(), &value - 1u8, &value + 1u8] {
            let owned = Nat(magnitude.clone());
            let external = magnitude.to_string().parse::<candid::Nat>().unwrap();
            let bytes = candid::encode_one(&external).unwrap();
            assert_eq!(encode_one(&owned, 8192).unwrap(), bytes);
            assert_eq!(decode_one::<Nat>(&bytes, limits).unwrap(), owned);
            let json = serde_json::to_vec(&owned).unwrap();
            assert_eq!(json, serde_json::to_vec(&external).unwrap());
            assert_eq!(serde_json::from_slice::<Nat>(&json).unwrap(), owned);
            let cbor = serde_cbor::to_vec(&owned).unwrap();
            assert_eq!(cbor, serde_cbor::to_vec(&external).unwrap());
            assert_eq!(serde_cbor::from_slice::<Nat>(&cbor).unwrap(), owned);
            assert_eq!(owned.to_string(), external.to_string());
        }
    }
}
#[test]
fn serde_admission_and_conversions_preserve_ranges() {
    for text in [
        "0",
        "1",
        "9223372036854775807",
        "18446744073709551615",
        "-1",
        "1.5",
        "[]",
        "[0,1]",
        "[4294967296]",
        "\"340282366920938463463374607431768211456\"",
        "\"1_000\"",
        "\"-1\"",
    ] {
        let own = serde_json::from_str::<Nat>(text).map(|n| n.0);
        let reference = serde_json::from_str::<candid::Nat>(text).map(|n| n.0);
        assert_eq!(own.is_ok(), reference.is_ok(), "{text}");
        if let (Ok(own), Ok(reference)) = (own, reference) {
            assert_eq!(own.to_string(), reference.to_string());
        }
    }
    assert!(Nat::from(u128::MAX) > u64::MAX);
    let owned = Nat::from(u128::MAX);
    let registry: candid::Nat = owned.clone().into();
    assert_eq!(Nat::from(registry), owned);
}

#[test]
fn tagged_serde_buffers_reject_empty_and_wrong_tags() {
    struct Tagged(Vec<u8>);
    impl<'de> serde::Deserializer<'de> for Tagged {
        type Error = serde::de::value::Error;
        fn deserialize_any<V: serde::de::Visitor<'de>>(
            self,
            visitor: V,
        ) -> Result<V::Value, Self::Error> {
            visitor.visit_byte_buf(self.0)
        }
        serde::forward_to_deserialize_any! {
            bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
            byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
            map struct enum identifier ignored_any
        }
    }
    for bytes in [vec![], vec![0], vec![2, 1]] {
        assert!(Nat::deserialize(Tagged(bytes)).is_err());
    }
    for bytes in [vec![1], vec![1, 0], vec![1, 255, 255]] {
        let own = Nat::deserialize(Tagged(bytes.clone())).unwrap();
        let reference = candid::Nat::deserialize(Tagged(bytes)).unwrap();
        assert_eq!(own.to_string(), reference.to_string());
    }
}