Skip to main content
Glama
number.rs4.68 kB
use std::f64; use serde::Deserialize; use crate::{ Args, generic, require, rule_err, }; #[derive(Debug, Clone, Deserialize)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] pub struct Validator { #[serde(default)] rules: Vec<Rule>, #[serde(flatten)] pub base: generic::Validator<f64, Flags>, } impl Validator { fn validate_safe(&self, value: f64) -> Result<(), (String, String)> { if !self.base.flags.extra_flags.r#unsafe { require( (JS_MIN_SAFE_INTEGER..=JS_MAX_SAFE_INTEGER).contains(&value), "number.unsafe", "unsafe number", )?; } Ok(()) } } impl Validator { pub fn validate(self, value: &Option<serde_json::Value>) -> Result<(), (String, String)> { self.base.validate_presence(value)?; if let Some(value) = value { let value = match value { serde_json::Value::Number(number) => number.as_f64(), serde_json::Value::String(string) => string.trim().parse().ok(), _ => None, } .ok_or_else(|| rule_err("number.base", "must be a number"))?; // Now that we have the float, validate it self.validate_safe(value)?; self.base.validate_value(&value)?; for rule in self.rules { rule.validate(&value)?; } } Ok(()) } pub fn rule_names(&self) -> Vec<&'static str> { let mut rule_names = self.base.rule_names(); rule_names.push("number.base"); if !self.base.flags.extra_flags.r#unsafe { rule_names.push("number.unsafe"); } rule_names.extend(self.rules.iter().map(Rule::rule_name)); rule_names } } const JS_MIN_SAFE_INTEGER: f64 = -9007199254740991.0; const JS_MAX_SAFE_INTEGER: f64 = 9007199254740991.0; #[derive(Debug, Clone, Deserialize)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] #[serde(tag = "name")] enum Rule { Greater(Args<Limit>), Integer, Less(Args<Limit>), Max(Args<Limit>), Min(Args<Limit>), // Multiple(Args<Multiple>), // Port, // Precision(Precision), // Sign(Args<SignArgs>), } impl Rule { fn validate(&self, value: &f64) -> Result<(), (String, String)> { match self { Rule::Integer => require(value.fract() == 0.0, "number.integer", "must be an integer"), Rule::Greater(rule) => require( value > &rule.args.limit, "number.greater", format!("must be greater than {}", rule.args.limit), ), Rule::Less(rule) => require( value < &rule.args.limit, "number.less", format!("must be less than {}", rule.args.limit), ), Rule::Max(rule) => require( value <= &rule.args.limit, "number.max", format!("must be less than or equal to {}", rule.args.limit), ), Rule::Min(rule) => require( value >= &rule.args.limit, "number.min", format!("must be greater than or equal to {}", rule.args.limit), ), } } fn rule_name(&self) -> &'static str { match self { Rule::Greater(_) => "number.greater", Rule::Integer => "number.integer", Rule::Less(_) => "number.less", Rule::Max(_) => "number.max", Rule::Min(_) => "number.min", } } } #[derive(Debug, Clone, Deserialize)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] struct Limit { limit: f64, } #[derive(Debug, Clone, Deserialize, Default)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] pub struct Flags { // Set true to not check if the number is in the safe range #[serde(default)] r#unsafe: bool, } // #[derive(Debug, Clone, Deserialize)] // #[serde(rename_all = "camelCase")] // #[serde(deny_unknown_fields)] // struct Precision { // limit: u64, // } // #[derive(Debug, Clone, Deserialize)] // #[serde(rename_all = "camelCase")] // #[serde(deny_unknown_fields)] // struct Multiple { // base: f64, // base_decimal_place: u64, // pfactor: f64, // } // #[derive(Debug, Clone, Deserialize)] // #[serde(rename_all = "camelCase")] // #[serde(deny_unknown_fields)] // struct SignArgs { // sign: Sign, // } // #[derive(Debug, Clone, Deserialize)] // #[serde(rename_all = "camelCase")] // #[serde(deny_unknown_fields)] // enum Sign { // Negative, // Positive, // }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server