qubit_argument/argument/float_argument.rs
1// =============================================================================
2// Copyright (c) 2025 - 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Ownership-preserving validation for floating-point arguments.
9
10use crate::argument::{
11 ArgumentError,
12 ArgumentErrorKind,
13 ArgumentResult,
14 ArgumentValue,
15 sealed::Sealed,
16};
17
18/// Validates properties specific to floating-point arguments.
19///
20/// This trait is implemented only for `f32` and `f64`. Successful validation
21/// returns the original value with its exact bit pattern unchanged.
22///
23/// The trait is sealed: downstream crates can use its methods but cannot add
24/// implementations for other types.
25///
26/// ```compile_fail
27/// use qubit_argument::{ArgumentResult, FloatArgument};
28///
29/// struct CustomFloat;
30///
31/// impl FloatArgument for CustomFloat {
32/// fn require_finite(self, _path: &str) -> ArgumentResult<Self> {
33/// Ok(self)
34/// }
35/// }
36/// ```
37pub trait FloatArgument: Sealed + Sized {
38 /// Requires this floating-point value to be finite.
39 ///
40 /// Success returns the original value. NaN returns
41 /// [`ArgumentErrorKind::NotANumber`]; positive or negative infinity returns
42 /// [`ArgumentErrorKind::NotFinite`] with the exact floating-point value at
43 /// `path`.
44 fn require_finite(self, path: &str) -> ArgumentResult<Self>;
45}
46
47macro_rules! impl_float_argument {
48 ($($float_type:ty),+ $(,)?) => {
49 $(
50 impl FloatArgument for $float_type {
51 /// Requires a finite value and preserves its exact bit pattern.
52 #[inline]
53 fn require_finite(self, path: &str) -> ArgumentResult<Self> {
54 if self.is_nan() {
55 Err(ArgumentError::new(
56 path,
57 ArgumentErrorKind::NotANumber,
58 ))
59 } else if self.is_finite() {
60 Ok(self)
61 } else {
62 Err(ArgumentError::new(
63 path,
64 ArgumentErrorKind::NotFinite {
65 actual: ArgumentValue::from(self),
66 },
67 ))
68 }
69 }
70 }
71 )+
72 };
73}
74
75impl_float_argument!(f32, f64);