Repository: mitsuhiko/minijinja (language: rust)

Issue:
Distinguish between `Value`s containing integers and floats
Hi, I would like to be able to distinguish between a Value representing integers (`ValueRepr::U64`, `ValueRepr::I64` etc.) and a Value representing a float (`ValueRepr::F64`).

Right now, there isn't a way to know whether a `Value` contains a float or int because
- The `ValueRepr` (`Value.0`) is private 
- `ValueKind` considers ints and floats all to be a `ValueKind::Number`
- Converting a `Value` doesn't reveal this information either, it just converts floats to ints and vice versa:

```rs
assert_eq!(Value::from(0.0).as_i64().unwrap(), 0);
assert_eq!(f64::try_from(Value::from(0)).unwrap(), 0.0);
```

This distinction can be quite useful if you want to format a value differently based on whether it's an int or float for example.

I'm happy to create a PR for this if that helps but I'm not sure what the best approach is.


Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 32e5d07e..fa71603c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,8 @@ All notable changes to MiniJinja are documented here.
   values.  #571
 - Changed sort order of `Ord` to avoid accidentally non total order
   that could cause panics on Rust 1.81.  #579
+- Added a `Value::is_integer` method to allow a user to tell floats
+  and true integers apart.  #580
 
 ## 2.2.0
 
diff --git a/minijinja/src/value/mod.rs b/minijinja/src/value/mod.rs
index 4fdac445..8fc43acf 100644
--- a/minijinja/src/value/mod.rs
+++ b/minijinja/src/value/mod.rs
@@ -979,6 +979,17 @@ impl Value {
         )
     }
 
+    /// Returns true if the number is a real integer.
+    ///
+    /// This can be used to distinguish `42` from `42.0`.  For the most part
+    /// the engine keeps these the same.
+    pub fn is_integer(&self) -> bool {
+        matches!(
+            self.0,
+            ValueRepr::U64(_) | ValueRepr::I64(_) | ValueRepr::I128(_) | ValueRepr::U128(_)
+        )
+    }
+
     /// Returns `true` if the map represents keyword arguments.
     pub fn is_kwargs(&self) -> bool {
         Kwargs::extract(self).is_some()


Test patch:
diff --git a/minijinja/src/tests.rs b/minijinja/src/tests.rs
index 0a648535..f3528a82 100644
--- a/minijinja/src/tests.rs
+++ b/minijinja/src/tests.rs
@@ -307,13 +307,7 @@ mod builtins {
     /// ```
     #[cfg_attr(docsrs, doc(cfg(feature = "builtins")))]
     pub fn is_integer(v: Value) -> bool {
-        matches!(
-            v.0,
-            crate::value::ValueRepr::U64(_)
-                | crate::value::ValueRepr::I64(_)
-                | crate::value::ValueRepr::U128(_)
-                | crate::value::ValueRepr::I128(_)
-        )
+        v.is_integer()
     }
 
     /// Checks if this value is a float