Repository: shuttle-hq/synth (language: rust)

Issue:
`unreachable` triggered on weightless single-variant categorical
**Describe the bug**
WIth a `categorical` containing only one variant with a weight of `0`, we happen upon an `unreachable` error.

**To Reproduce**
Steps to reproduce the behavior:
1. Schema (if applicable)
```
{
    "type": "array",
    "length": 1,
    "content": {
        "type": "object",
        "cat": {
            "type": "string",
            "categorical": {
                "empty": 0
            }
        }
    }
}
```
2. See error
```
thread 'main' panicked at 'internal error: entered unreachable code', /home/andre/projects/synth/core/src/schema/content/categorical.rs:82:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

**Expected behavior**
The single category should be used regardless of weight and also a warning about a single-variant categorical should be emitted.

**Environment (please complete the following information):**
 - OS: any
 - Version: 0.5.6


Discussion / hints:

Fix patch:
diff --git a/core/src/schema/content/categorical.rs b/core/src/schema/content/categorical.rs
index 1ba87f26..b07f17e5 100644
--- a/core/src/schema/content/categorical.rs
+++ b/core/src/schema/content/categorical.rs
@@ -71,6 +71,10 @@ impl<T: CategoricalType> From<CategoricalShadow<T>> for Categorical<T> {
 
 impl<T: CategoricalType> Distribution<T> for Categorical<T> {
     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T {
+        if self.seen.len() == 1 {
+            // unwrap() is always OK here because len == 1
+            return self.seen.keys().next().unwrap().clone();
+        }
         let f = rng.gen_range(0.0..1.0);
         let mut index = (f * self.total as f64).floor() as i64;
         for (k, v) in self.seen.iter() {
@@ -129,4 +133,14 @@ pub mod tests {
         let categorical_json = json!({});
         assert!(serde_json::from_value::<Categorical<String>>(categorical_json).is_err())
     }
+
+    #[test]
+    fn test_weightless_single_invariant() {
+        let categorical_json = json!({ "foo": 0 });
+        assert_eq!(
+            "foo",
+            serde_json::from_value::<Categorical<String>>(categorical_json)
+                .unwrap()
+                .sample(&mut rand::thread_rng()))
+    }
 }


Test patch: