///|
/// The five OpenFeature flag types. Integers remain distinct from floating point.
pub(all) enum FlagType {
Boolean
Integer
Float
String
Structure
} derive(Eq)
///|
pub extend FlagType with Eq::{equal, not_equal}
///|
/// Structure flags accept JSON objects, arrays and null, not JSON scalars.
/// Raw enum construction does not validate or take ownership of mutable JSON.
/// Providers and callbacks must validate their result before publishing it and
/// use copy() when crossing an ownership boundary.
pub(all) enum FlagValue {
Boolean(Bool)
Integer(Int64)
Float(Double)
String(String)
Structure(Json)
}
///|
pub fn FlagValue::flag_type(self : FlagValue) -> FlagType {
match self {
Boolean(_) => Boolean
Integer(_) => Integer
Float(_) => Float
String(_) => String
Structure(_) => Structure
}
}
///|
/// Copy a validated flag, detaching every mutable JSON container.
/// Invalid JSON trees are replaced by null; call validate() to report errors.
pub fn FlagValue::copy(self : FlagValue) -> FlagValue {
match self {
Boolean(value) => Boolean(value)
Integer(value) => Integer(value)
Float(value) => Float(value)
String(value) => String(value)
Structure(value) => Structure(copy_json(value))
}
}
///|
pub fn FlagValue::validate(self : FlagValue) -> Result[Unit, SdkError] {
match self {
Float(value) =>
if value.is_nan() || value.is_inf() {
Err(SdkError::new(TypeMismatch, "floating point flag must be finite"))
} else {
Ok(())
}
Structure(value) =>
match value {
Object(_) | Array(_) | Null => validate_json(value)
_ =>
Err(
SdkError::new(
TypeMismatch,
"structure flag must be object, array or null",
),
)
}
Boolean(_) | Integer(_) | String(_) => Ok(())
}
}
///|
/// Accessors perform exact type checks, never coercion or numeric narrowing.
pub fn FlagValue::as_boolean(self : FlagValue) -> Bool? {
match self {
Boolean(value) => Some(value)
_ => None
}
}
///|
pub fn FlagValue::as_integer(self : FlagValue) -> Int64? {
match self {
Integer(value) => Some(value)
_ => None
}
}
///|
pub fn FlagValue::as_float(self : FlagValue) -> Double? {
match self {
Float(value) => Some(value)
_ => None
}
}
///|
pub fn FlagValue::as_string(self : FlagValue) -> String? {
match self {
String(value) => Some(value)
_ => None
}
}
///|
/// The returned JSON is detached, including nested objects and arrays.
pub fn FlagValue::as_structure(self : FlagValue) -> Json? {
match self {
Structure(value) => Some(copy_json(value))
_ => None
}
}
///|
/// Serialize a validated flag. Int64's original decimal representation avoids
/// loss of precision when JSON is stringified, despite Json's Double payload.
/// This is not a validation API: call validate() before serialization.
pub fn FlagValue::to_json(self : FlagValue) -> Json {
match self {
Boolean(value) => Json::boolean(value)
Integer(value) => Json::number(value.to_double(), repr=value.to_string())
Float(value) => Json::number(value)
String(value) => Json::string(value)
Structure(value) => copy_json(value)
}
}