configs/
validated_types.rs1pub use schema_kit::{NonEmptyVec, NonZeroU64, PositiveF64, PositiveI32, PositiveI64};
8
9use std::fmt;
10
11use schemars::JsonSchema;
12use schemars::r#gen::SchemaGenerator;
13use schemars::schema::{InstanceType, Schema, SchemaObject};
14use serde::{Deserialize, Deserializer, Serialize};
15
16#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Serialize)]
21#[serde(transparent)]
22pub struct WeightMultiplier(f64);
23
24impl WeightMultiplier {
25 pub fn new(value: f64) -> Self {
27 assert!(
28 value >= 1.0,
29 "WeightMultiplier: expected >= 1.0, got {value}"
30 );
31 Self(value)
32 }
33
34 pub fn get(self) -> f64 {
35 self.0
36 }
37}
38
39impl<'de> Deserialize<'de> for WeightMultiplier {
40 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
41 let v = f64::deserialize(deserializer)?;
42 if v < 1.0 {
43 return Err(serde::de::Error::custom(format!(
44 "expected weight multiplier >= 1.0, got {v}"
45 )));
46 }
47 Ok(Self(v))
48 }
49}
50
51impl JsonSchema for WeightMultiplier {
52 fn schema_name() -> String {
53 "WeightMultiplier".to_owned()
54 }
55
56 fn json_schema(_generator: &mut SchemaGenerator) -> Schema {
57 SchemaObject {
58 instance_type: Some(InstanceType::Number.into()),
59 number: Some(Box::new(schemars::schema::NumberValidation {
60 minimum: Some(1.0),
61 ..Default::default()
62 })),
63 ..Default::default()
64 }
65 .into()
66 }
67}
68
69impl fmt::Display for WeightMultiplier {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 self.0.fmt(f)
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn weight_multiplier_rejects_below_one() {
81 let result: Result<WeightMultiplier, _> = serde_json::from_str("0.5");
82 assert!(result.is_err());
83 }
84
85 #[test]
86 fn weight_multiplier_accepts_one() {
87 let v: WeightMultiplier = serde_json::from_str("1.0").unwrap();
88 assert!((v.get() - 1.0).abs() < f64::EPSILON);
89 }
90}