/// Lenient readers for bridge maps: the platform channel hands numbers over as /// int or double depending on the Java type, and nested maps as `Map`. library; double? asDouble(Object? v) => v is num ? v.toDouble() : null; int? asInt(Object? v) => v is num ? v.toInt() : null; bool? asBool(Object? v) => v is bool ? v : null; String? asString(Object? v) => v is String ? v : null; Map? asMap(Object? v) => v is Map ? Map.from(v) : null; List> asMapList(Object? v) => v is List ? >[for (final Object? e in v) if (e is Map) Map.from(e)] : const >[]; /// Doubles that are actually reported: the SDK fills unknown floats with NaN. double? finite(Object? v) { final double? d = asDouble(v); return d == null || d.isNaN || d.isInfinite ? null : d; } /// Structural equality for decoded channel values (maps, lists, scalars). bool deepEquals(Object? a, Object? b) { if (identical(a, b)) return true; if (a is Map && b is Map) { if (a.length != b.length) return false; for (final Object? k in a.keys) { if (!b.containsKey(k) || !deepEquals(a[k], b[k])) return false; } return true; } if (a is List && b is List) { if (a.length != b.length) return false; for (int i = 0; i < a.length; i++) { if (!deepEquals(a[i], b[i])) return false; } return true; } return a == b; }