#![deny(rustdoc::broken_intra_doc_links)]

//! Type-safe scalar wrappers and numerical utilities for mathematical grid operations.
//!
//! This module provides strongly-typed wrappers around primitive scalar types to prevent value
//! confusion and enforce mathematical constraints at compile time. These types are fundamental
//! building blocks that ensure correctness in grid construction, interval arithmetic, and
//! numerical computations throughout the [`grid1d`](crate) library.
//!
//! ## Core Design Philosophy
//!
//! ### Type Safety Through Distinct Types
//!
//! Rather than using raw primitives like `usize` and `f64` directly, this module provides
//! semantically meaningful types that encode mathematical constraints:
//!
//! ```rust
//! use grid1d::{Grid1D, intervals::*, scalars::*};
//! use try_create::TryNew;
//!
//! // These are different types that cannot be confused:
//! let num_intervals = NumIntervals::try_new(10).unwrap();     // Must be ≥ 1
//! let interval_id = IntervalId::new(5);                       // Any non-negative integer
//! let num_points = PositiveNumPoints1D::try_new(11).unwrap(); // Must be ≥ 1
//! let size = Size::new(0);                                    // Can be zero
//! let positive_size = PositiveSize::try_new(1).unwrap();     // Must be ≥ 1
//!
//! // Compile-time prevention of logical errors:
//! let domain = IntervalClosed::new(0.0, 1.0);
//! // let grid = Grid1D::uniform(domain, interval_id);  // ← Compilation error!
//! let grid = Grid1D::uniform(domain, num_intervals);   // ✓ Correct
//! ```
//!
//! ### Mathematical Constraint Enforcement
//!
//! Each type enforces specific mathematical properties essential for grid operations:
//!
//! | Type | Constraint | Mathematical Meaning | Use Cases |
//! |------|------------|---------------------|-----------|
//! | [`Size`] | `≥ 0` | Non-negative counting | General sizes, possibly empty collections |
//! | [`PositiveSize`] | `≥ 1` | Positive counting | Non-empty collections, array dimensions |
//! | [`NumIntervals`] | `≥ 1` | Interval count | Grid subdivision (cannot have zero intervals) |
//! | [`IntervalId`] | `≥ 0` | Index identifier | Zero-based interval indexing |
//! | [`PositiveNumPoints1D`] | `≥ 1` | Point count | Grid points (cannot have zero points) |
//! | [`num_valid::scalars::PositiveRealScalar<T>`] | `> 0` | Positive reals | Lengths, tolerances, positive quantities (in `num_valid`) |
//!
//! ## Generic Scalar Support with [`num_valid::RealScalar`]
//!
//! All real-valued types in this module are generic over [`num_valid::RealScalar`], enabling
//! the same mathematical operations across different scalar backends:
//!
//! ```rust
//! use num_valid::{RealNative64StrictFiniteInDebug, RealScalar};
//! use num_valid::scalars::AbsoluteTolerance;
//! use try_create::TryNew;
//!
//! // Different scalar types for different use cases:
//! let fast_tolerance = AbsoluteTolerance::try_new(1e-10_f64).unwrap(); // Maximum performance
//! let safe_tolerance = AbsoluteTolerance::try_new(
//!     RealNative64StrictFiniteInDebug::try_new(1e-10).unwrap()).unwrap(); // Debug validation
//!
//! // Both have the same API and mathematical properties
//! assert_eq!(*fast_tolerance.as_ref(), 1e-10);
//! ```
//!
//! ## Size and Counting Types
//!
//! ### Basic Size Types
//!
//! The foundational size types form a hierarchy based on mathematical constraints:
//!
//! ```rust
//! use grid1d::scalars::*;
//! use try_create::TryNew;
//!
//! // Size can be zero or positive
//! let empty_size = Size::new(0);              // Valid: represents empty collection
//! let non_empty_size = Size::new(5);          // Valid: represents 5 elements
//!
//! // PositiveSize must be strictly positive  
//! let positive = PositiveSize::try_new(5).unwrap();  // Valid: 5 ≥ 1
//! let invalid = PositiveSize::try_new(0);            // Error: 0 < 1
//! assert!(invalid.is_err());
//!
//! // Conversions preserve mathematical relationships
//! let size_from_positive: Size = positive.into();   // Always succeeds
//! let positive_from_size = PositiveSize::try_from(empty_size); // May fail
//! assert!(positive_from_size.is_err());
//! ```
//!
//! ### Grid-Specific Counting Types
//!
//! Specialized types enforce domain-specific constraints:
//!
//! ```rust
//! use grid1d::{scalars::*, intervals::*, Grid1D};
//! use try_create::TryNew;
//!
//! // NumIntervals: must have at least one interval for grid subdivision
//! let num_intervals = NumIntervals::try_new(4).unwrap();
//! let invalid_intervals = NumIntervals::try_new(0);  // Error: cannot subdivide into 0 intervals
//! assert!(invalid_intervals.is_err());
//!
//! // PositiveNumPoints1D: must have at least one point
//! let num_points = PositiveNumPoints1D::try_new(5).unwrap();
//! let invalid_points = PositiveNumPoints1D::try_new(0);  // Error: cannot have 0 points
//! assert!(invalid_points.is_err());
//!
//! // IntervalId: zero-based indexing (can be 0)
//! let first_interval = IntervalId::new(0);    // Valid: first interval
//! let last_interval = IntervalId::new(3);     // Valid: fourth interval (0-indexed)
//!
//! // Type safety in grid construction
//! let domain = IntervalClosed::new(0.0, 1.0);
//! let grid = Grid1D::uniform(domain, num_intervals);  // ✓ Correct type
//! // let wrong = Grid1D::uniform(domain, first_interval);  // ← Compilation error!
//! ```
//!
//! ### Positive Integer Type Unification
//!
//! The [`PositiveIntTrait`] provides a unified interface for all positive integer types:
//!
//! ```rust
//! use grid1d::scalars::*;
//! use try_create::TryNew;
//!
//! // Generic function that works with any positive integer type
//! fn analyze_count<T: PositiveIntTrait>(count: T) -> String {
//!     match *count.as_ref() {
//!         1 => format!("Single item: {}", count),
//!         n => format!("Multiple items ({}): {}", n, count),
//!     }
//! }
//!
//! let intervals = NumIntervals::try_new(5).unwrap();
//! let points = PositiveNumPoints1D::try_new(6).unwrap();
//! let size = PositiveSize::try_new(10).unwrap();
//!
//! println!("{}", analyze_count(intervals));  // "Multiple items (5): 5"
//! println!("{}", analyze_count(points));     // "Multiple items (6): 6"
//! println!("{}", analyze_count(size));       // "Multiple items (10): 10"
//!
//! // Seamless conversions between positive integer types
//! let intervals_from_size: NumIntervals = size.into();
//! let points_from_intervals: PositiveNumPoints1D = intervals.into();
//! assert_eq!(*intervals_from_size.as_ref(), 10);
//! assert_eq!(*points_from_intervals.as_ref(), 5);
//! ```
//!
//! ## Tolerance and Error Control Types (in `num_valid`)
//!
//! ### Absolute and Relative Tolerances
//!
//! Mathematical tolerances enforce non-negativity and provide conversion utilities.
//! These types are now in the [`num_valid::scalars`] module:
//!
//! ```rust
//! use num_valid::scalars::{AbsoluteTolerance, RelativeTolerance};
//! use try_create::TryNew;
//!
//! // Absolute tolerance: fixed error bounds
//! let abs_tol = AbsoluteTolerance::try_new(1e-12).unwrap();
//! let zero_abs = AbsoluteTolerance::<f64>::zero();
//! let epsilon_abs = AbsoluteTolerance::<f64>::epsilon();
//!
//! // Relative tolerance: proportional error bounds  
//! let rel_tol = RelativeTolerance::try_new(1e-6).unwrap();
//! let zero_rel = RelativeTolerance::<f64>::zero();
//! let epsilon_rel = RelativeTolerance::<f64>::epsilon();
//!
//! // Convert relative to absolute tolerance based on reference value
//! let reference_value = 1000.0;
//! let computed_abs_tol = rel_tol.absolute_tolerance(reference_value);
//! assert_eq!(*computed_abs_tol.as_ref(), 1e-3); // 1e-6 * 1000.0 = 1e-3
//!
//! // Error handling for invalid tolerances
//! let negative_tol = AbsoluteTolerance::try_new(-1e-6);
//! assert!(negative_tol.is_err()); // Tolerances cannot be negative
//! ```
//!
//! ### Positive Real Scalars (in `num_valid`)
//!
//! The [`num_valid::scalars::PositiveRealScalar<T>`] type ensures strict positivity for quantities
//! that must be greater than zero:
//!
//! ```rust
//! use grid1d::intervals::*;
//! use num_valid::scalars::PositiveRealScalar;
//! use try_create::TryNew;
//!
//! // Valid positive values
//! let length = PositiveRealScalar::try_new(2.5).unwrap();
//! let tiny_value = PositiveRealScalar::try_new(f64::MIN_POSITIVE).unwrap();
//! let large_value = PositiveRealScalar::try_new(1e100).unwrap();
//!
//! // Invalid values are rejected
//! let zero_error = PositiveRealScalar::try_new(0.0);
//! let negative_error = PositiveRealScalar::try_new(-1.0);
//! assert!(zero_error.is_err());
//! assert!(negative_error.is_err());
//!
//! // Use in interval length calculations
//! let interval = IntervalClosed::new(1.0, 3.0);
//! let length = interval.length(); // Returns PositiveRealScalar<f64>
//! assert_eq!(*length.as_ref(), 2.0);
//! ```
//!
//! ## Hash-Safe Real Numbers
//!
//! ### [`HashableScalar<T>`] for Collections
//!
//! Real numbers are not naturally hashable due to NaN values. [`HashableScalar<T>`] provides
//! a wrapper that enables using finite real values as keys in hash-based collections:
//!
//! ```rust
//! use grid1d::scalars::HashableScalar;
//! use std::collections::{HashMap, HashSet};
//!
//! // Enable real numbers as hash keys
//! let mut point_data: HashMap<HashableScalar<f64>, String> = HashMap::new();
//! let mut coordinate_set: HashSet<HashableScalar<f64>> = HashSet::new();
//!
//! // Store data indexed by coordinate values
//! point_data.insert(HashableScalar::new(1.5), "Boundary point".to_string());
//! point_data.insert(HashableScalar::new(2.7), "Interior point".to_string());
//!
//! coordinate_set.insert(HashableScalar::new(0.0));
//! coordinate_set.insert(HashableScalar::new(1.0));
//!
//! // Safe lookup and iteration
//! let boundary_info = point_data.get(&HashableScalar::new(1.5));
//! assert_eq!(boundary_info, Some(&"Boundary point".to_string()));
//!
//! // Only finite values are allowed (enforced in debug mode)
//! #[cfg(debug_assertions)]
//! {
//!     std::panic::catch_unwind(|| {
//!         HashableScalar::new(f64::NAN); // Panics in debug
//!     }).expect_err("Should panic on NaN");
//! }
//! ```
//!
//! ## Type Conversions and Interoperability
//!
//! ### Safe Conversion Patterns
//!
//! The module provides both infallible and fallible conversions between related types:
//!
//! ```rust
//! use grid1d::scalars::*;
//! use try_create::TryNew;
//!
//! // Infallible conversions (always succeed)
//! let positive_size = PositiveSize::try_new(5).unwrap();
//! let size: Size = positive_size.into();              // PositiveSize → Size (always valid)
//! let num_intervals: NumIntervals = positive_size.into(); // PositiveSize → NumIntervals
//!
//! // Fallible conversions (may fail due to constraints)
//! let zero_size = Size::new(0);
//! let positive_attempt = PositiveSize::try_from(zero_size);
//! assert!(positive_attempt.is_err()); // 0 is not ≥ 1
//!
//! let valid_size = Size::new(3);
//! let positive_success = PositiveSize::try_from(valid_size);
//! assert!(positive_success.is_ok()); // 3 ≥ 1
//! ```
//!
//! ### Integration with Grid Operations
//!
//! These types integrate seamlessly with grid construction and manipulation:
//!
//! ```rust
//! use grid1d::{
//!     Grid1D, HasCoords1D, IntervalPartition, HasDomain1D,
//!     intervals::*, scalars::*,
//! };
//! use try_create::TryNew;
//!
//! // Type-safe grid construction pipeline
//! let domain = IntervalClosed::new(0.0, 10.0);
//! let num_intervals = NumIntervals::try_new(20).unwrap();
//! let grid = Grid1D::uniform(domain.clone(), num_intervals);
//! let coordinates = grid.coords();
//! let num_points = coordinates.num_points(); // Returns PositiveNumPoints1D
//!
//! // Type-safe interval access
//! let interval_id = IntervalId::new(5);
//! let specific_interval = grid.interval(&interval_id);
//!
//! // All operations maintain type safety
//! assert_eq!(*num_intervals.as_ref(), 20);
//! assert!(*num_points.as_ref() >= 1); // Guaranteed by type system
//! ```
//!
//! ## Error Handling and Validation
//!
//! ### Comprehensive Error Types
//!
//! Each validated type provides specific error information for debugging.
//! Error types for tolerance and positive scalar types are in [`num_valid::scalars`]:
//!
//! ```rust
//! use num_valid::scalars::{AbsoluteTolerance, PositiveRealScalar, ErrorsTolerance, ErrorsPositiveRealScalar};
//! use try_create::TryNew;
//!
//! // Detailed error reporting for tolerance validation
//! match AbsoluteTolerance::try_new(-1e-6) {
//!     Err(ErrorsTolerance::NegativeValue { value, backtrace }) => {
//!         println!("Invalid tolerance: {} (negative)", value);
//!         // Backtrace available for debugging
//!     }
//!     _ => unreachable!(),
//! }
//!
//! // Comprehensive positive scalar validation
//! match PositiveRealScalar::try_new(0.0) {
//!     Err(ErrorsPositiveRealScalar::ZeroValue { backtrace }) => {
//!         println!("Zero value rejected for positive scalar");
//!     }
//!     _ => unreachable!(),
//! }
//!
//! match PositiveRealScalar::try_new(-5.0) {
//!     Err(ErrorsPositiveRealScalar::NegativeValue { value, backtrace }) => {
//!         println!("Negative value {} rejected", value);
//!     }
//!     _ => unreachable!(),
//! }
//! ```
//!
//! ### Debug vs Release Validation
//!
//! The module follows the grid1d pattern of providing debug-time validation with release-time performance:
//!
//! ```rust
//! use grid1d::scalars::*;
//! use try_create::TryNew;
//!
//! // Debug assertions for immediate feedback during development
//! #[cfg(debug_assertions)]
//! {
//!     // HashableScalar panics in debug builds on invalid input
//!     std::panic::catch_unwind(|| {
//!         HashableScalar::new(f64::NAN);
//!     }).expect_err("NaN should panic in debug");
//! }
//!
//! // Explicit try_new() calls provide fallible validation in all builds
//! let positive_result = PositiveSize::try_new(0);
//! assert!(positive_result.is_err()); // Zero is not positive
//!
//! let tolerance_result = num_valid::scalars::AbsoluteTolerance::try_new(-1.0);
//! assert!(tolerance_result.is_err()); // Negative tolerance invalid
//! ```
//!
//! ## Performance Characteristics
//!
//! ### Zero-Cost Abstractions
//!
//! All types in this module are designed as zero-cost abstractions:
//!
//! | Type                     | Memory Layout    | Runtime Cost  |
//! | -------------------------|------------------|---------------|
//! | [`Size`]                 | Single [`usize`] | Zero overhead |
//! | [`PositiveSize`]         | Single [`usize`] | Zero overhead |
//! | [`NumIntervals`]         | Single [`usize`] | Zero overhead |
//! | [`IntervalId`]           | Single [`usize`] | Zero overhead |
//! | [`PositiveNumPoints1D`]  | Single [`usize`] | Zero overhead |
//! | [`HashableScalar<T>`]    | Single `T` ([`RealScalar`]) value | Zero overhead |
//!
//! Types in [`num_valid::scalars`] (same zero-cost characteristics):
//!
//! | Type                     | Memory Layout    | Runtime Cost  |
//! | -------------------------|------------------|---------------|
//! | `AbsoluteTolerance<T>`   | Single `T` ([`RealScalar`]) value | Zero overhead |
//! | `RelativeTolerance<T>`   | Single `T` ([`RealScalar`]) value | Zero overhead |
//! | `PositiveRealScalar<T>`  | Single `T` ([`RealScalar`]) value | Zero overhead |
//! | `NonNegativeRealScalar<T>`| Single `T` ([`RealScalar`]) value | Zero overhead |
//!
//! ### Optimization Notes
//!
//! - **Compile-Time Validation**: Type constraints are enforced at compile time where possible
//! - **Inlined Operations**: All accessor methods are marked for inlining
//! - **Memory Efficiency**: Wrapper types have identical memory layout to wrapped primitives
//! - **Debug vs Release**: Validation overhead only in debug builds, maximum performance in release
//!
//! ## Advanced Usage Patterns
//!
//! ### Generic Programming with Scalar Types
//!
//! The scalar types enable writing generic functions that work across different constraint levels:
//!
//! ```rust
//! use grid1d::scalars::*;
//! use try_create::TryNew;
//!
//! // Generic function that works with any positive counting type
//! fn analyze_positive_count<T: PositiveIntTrait>(count: T) -> String {
//!     match *count.as_ref() {
//!         1 => format!("Single item: {}", count),
//!         n => format!("Multiple items ({}): {}", n, count),
//!     }
//! }
//!
//! let intervals = NumIntervals::try_new(5).unwrap();
//! let points = PositiveNumPoints1D::try_new(6).unwrap();
//! let size = PositiveSize::try_new(10).unwrap();
//!
//! println!("{}", analyze_positive_count(intervals));
//! println!("{}", analyze_positive_count(points));
//! println!("{}", analyze_positive_count(size));
//! ```
//!
//! ### Tolerance-Based Comparisons
//!
//! Combine tolerance types with generic scalar support for robust numerical comparisons:
//!
//! ```rust
//! use num_valid::RealScalar;
//! use num_valid::scalars::AbsoluteTolerance;
//! use try_create::TryNew;
//!
//! fn approximately_equal<T: RealScalar>(
//!     a: T,
//!     b: T,
//!     tolerance: &AbsoluteTolerance<T>
//! ) -> bool {
//!     let diff = (a - b).abs();
//!     &diff <= tolerance.as_ref()
//! }
//!
//! let tolerance = AbsoluteTolerance::try_new(1e-10).unwrap();
//! let a = 1.00000000015;
//! let b = 1.00000000020;
//!
//! assert!(approximately_equal(a, b, &tolerance));
//! ```
//!
//! ## References and Integration
//!
//! This module integrates with other grid1d components:
//!
//! - **[`crate::bounds`]**: Uses [`num_valid::scalars::PositiveRealScalar`] for validated interval lengths
//! - **[`crate::intervals`]**: Uses [`num_valid::scalars::PositiveRealScalar`] in length calculations
//! - **[`crate::Grid1D`]**: Uses [`NumIntervals`] and [`IntervalId`] for type-safe grid operations
//! - **[`num_valid`]**: Provides the [`RealScalar`] foundation and scalar wrapper types
//!   ([`num_valid::scalars::AbsoluteTolerance`], [`num_valid::scalars::PositiveRealScalar`], etc.)
//!
//! For detailed usage examples, see the individual type documentation and the comprehensive
//! test suite that demonstrates all validation scenarios and edge cases.

use derive_more::{AsRef, Display};
use duplicate::duplicate_item;
use into_inner::IntoInner;
use num_valid::{RealScalar, core::errors::capture_backtrace, kernels::RawScalarTrait};
use nutype::nutype;
use serde::{Deserialize, Serialize};
use std::{
    backtrace::Backtrace,
    hash::{Hash, Hasher},
};
use thiserror::Error;
use try_create::TryNew;

//------------------------------------------------------------------------------------------------------------
#[nutype(derive(
    Debug,
    Clone,
    Copy,
    PartialEq,
    Eq,
    PartialOrd,
    Ord,
    Display,
    AsRef,
    Hash,
    Serialize,
    Deserialize
))]
/// Type indicating a generic ***size***, i.e. a **non-negative integer**.
pub struct Size(usize);

impl From<PositiveSize> for Size {
    /// Build a [`Size`] instance from a [`PositiveSize`].
    fn from(item: PositiveSize) -> Self {
        Size::new(item.into_inner())
    }
}
//------------------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------------------
/// Trait for types representing a positive integer (≥ 1).
///
/// This trait abstracts over various positive integer types like [`PositiveSize`],
/// [`NumIntervals`], and [`PositiveNumPoints1D`], allowing them to be used
/// interchangeably in generic functions.
///
/// Any type implementing this trait is guaranteed to:
/// 1.  Wrap a `usize` value.
/// 2.  Enforce that the value is always greater than or equal to 1.
/// 3.  Be convertible to and from other types that also implement this trait.
pub trait PositiveIntTrait:
    AsRef<usize>
    + From<PositiveSize>
    + Into<PositiveSize>
//    + From<NumIntervals>
//    + Into<NumIntervals>
//    + From<PositiveNumPoints1D>
//    + Into<PositiveNumPoints1D>
    + TryFrom<Size>
    + IntoInner<InnerType = usize>
    + TryNew<Error = ErrorsPositiveInt>
    + Copy
    + Clone
    + PartialEq
    + Eq
    + PartialOrd
    + Ord
    + Hash
    + std::fmt::Debug
    + std::fmt::Display
    + Serialize
    + for<'a> Deserialize<'a>
{
}

#[duplicate_item(
    In Out;
    [NumIntervals] [PositiveSize];
    [NumIntervals] [PositiveNumPoints1D];
    [PositiveNumPoints1D] [PositiveSize];
    [PositiveNumPoints1D] [NumIntervals];
    [PositiveSize] [NumIntervals];
    [PositiveSize] [PositiveNumPoints1D];
)]
impl From<In> for Out {
    #[inline(always)]
    fn from(value: In) -> Self {
        Self(value.into_inner())
    }
}

#[duplicate_item(
    T;
    [NumIntervals];
    [PositiveSize];
    [PositiveNumPoints1D];
)]
impl TryFrom<Size> for T {
    type Error = ErrorsPositiveInt;

    /// Build a [`Size`] instance from a type that implements [`PositiveIntTrait`].
    ///
    /// # Returns
    /// - `Ok` if `size >= 1`;
    /// - `Err` if `size == 0`.
    #[inline(always)]
    fn try_from(size: Size) -> Result<Self, Self::Error> {
        T::try_new(size.into_inner())
    }
}

impl PositiveIntTrait for PositiveSize {}
impl PositiveIntTrait for NumIntervals {}
impl PositiveIntTrait for PositiveNumPoints1D {}
//------------------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------------------
/// Error type for validated positive integer wrappers.
///
/// This enum defines all possible errors that can occur when constructing validated
/// positive integer types like [`PositiveSize`], [`NumIntervals`], and [`PositiveNumPoints1D`].
/// These types enforce the constraint that values must be strictly positive (≥ 1),
/// rejecting zero values at construction time.
///
/// # Purpose
///
/// Positive integer types are used throughout the codebase to encode domain constraints
/// at the type level, preventing invalid states like:
/// - Zero-sized grids or domains
/// - Empty interval partitions (zero intervals)
/// - Point collections with no points
///
/// By using validated types with this error enum, these constraints are enforced at
/// compile time through the type system, eliminating an entire class of runtime errors.
///
/// # Error Variants
///
/// - [`ErrorsPositiveInt::ZeroValue`]: The only error case, indicating that a zero value
///   was provided where a strictly positive integer was required.
///
/// # Usage in Type System
///
/// This error type is used by:
/// - [`TryNew::try_new()`] implementations for positive integer types
/// - [`TryFrom<Size>`] conversions that validate positivity
/// - Any operation that constructs positive integer wrappers
///
/// # Examples
///
/// ## Basic Usage
///
/// ```rust
/// use grid1d::scalars::{NumIntervals, ErrorsPositiveInt};
/// use try_create::TryNew;
///
/// // Valid construction (≥ 1)
/// let valid = NumIntervals::try_new(5);
/// assert!(valid.is_ok());
/// assert_eq!(valid.unwrap().as_ref(), &5);
///
/// // Invalid construction (zero)
/// let invalid = NumIntervals::try_new(0);
/// assert!(invalid.is_err());
///
/// if let Err(ErrorsPositiveInt::ZeroValue { .. }) = invalid {
///     // Expected error: zero is not positive
/// }
/// ```
///
/// ## Error Handling in Grid Construction
///
/// ```rust
/// use grid1d::{Grid1D, intervals::*, scalars::NumIntervals};
/// use try_create::TryNew;
///
/// let domain = IntervalClosed::new(0.0, 1.0);
///
/// // Attempt to create grid with zero intervals
/// let num_intervals = NumIntervals::try_new(0);
///
/// if let Err(e) = num_intervals {
///     eprintln!("Cannot create grid: {}", e);
///     // Output: "The input value is zero (it must be strictly positive"
/// }
/// ```
///
/// ## Type Conversion with Validation
///
/// ```rust
/// use grid1d::scalars::{Size, PositiveSize, ErrorsPositiveInt};
/// use try_create::TryNew;
///
/// // Size allows zero, PositiveSize does not
/// let size = Size::new(0);
/// let positive_result: Result<PositiveSize, ErrorsPositiveInt> = size.try_into();
///
/// assert!(positive_result.is_err());
/// ```
///
/// ## Pattern Matching for Error Details
///
/// ```rust
/// use grid1d::scalars::{NumIntervals, ErrorsPositiveInt};
/// use try_create::TryNew;
///
/// fn create_partition(n: usize) -> Result<NumIntervals, String> {
///     NumIntervals::try_new(n).map_err(|e| match e {
///         ErrorsPositiveInt::ZeroValue { backtrace } => {
///             format!("Invalid partition: cannot have zero intervals\n{}", backtrace)
///         }
///     })
/// }
///
/// assert!(create_partition(0).is_err());
/// assert!(create_partition(5).is_ok());
/// ```
///
/// # Error Message
///
/// The error message is designed to be self-explanatory:
/// ```text
/// The input value is zero (it must be strictly positive
/// ```
///
/// # Backtrace
///
/// Each error variant includes a [`Backtrace`] field for debugging. The backtrace is
/// force-captured at the error creation site, enabling precise error source tracking
/// in complex call stacks.
///
/// # Design Rationale
///
/// **Why an enum with one variant?**
/// - Extensibility: Future positive integer constraints can be added without breaking changes
/// - Consistency: Matches the error pattern used throughout the codebase
/// - Type safety: Explicit error type distinct from generic validation errors
///
/// **Why force-capture backtraces?**
/// - Zero values often indicate logic errors deep in computation chains
/// - Backtraces help identify the source of invalid state propagation
/// - Minimal performance impact since errors are exceptional cases
///
/// # See Also
///
/// - [`PositiveSize`]: Validated wrapper for positive `usize` representing sizes
/// - [`NumIntervals`]: Validated wrapper for positive number of intervals
/// - [`PositiveNumPoints1D`]: Validated wrapper for positive number of 1D points
/// - [`crate::ErrorsGrid1D`]: Grid-specific errors that may wrap this error type
/// - [`try_create::TryNew`]: Trait providing validated construction
#[derive(Debug, Error)]
pub enum ErrorsPositiveInt {
    /// Error variant indicating a zero value was provided where a strictly positive integer was required.
    ///
    /// # Context
    ///
    /// This error occurs when attempting to construct any positive integer type
    /// (like [`PositiveSize`], [`NumIntervals`], [`PositiveNumPoints1D`]) with a value of zero.
    ///
    /// # Mathematical Constraint
    ///
    /// These types represent counts or sizes in mathematical contexts where zero is meaningless:
    /// - Grid sizes: A grid must have at least one cell
    /// - Interval counts: An interval partition must contain at least one interval
    /// - Point collections: Must contain at least one point to be useful
    ///
    /// # Fields
    ///
    /// - `backtrace`: Captured stack trace showing where the invalid value originated.
    ///   Force-captured to aid debugging of complex validation failures.
    ///
    /// # Error Message
    ///
    /// ```text
    /// The input value is zero (it must be strictly positive
    /// ```
    ///
    /// # Examples
    ///
    /// ```rust
    /// use grid1d::scalars::{PositiveSize, ErrorsPositiveInt};
    /// use try_create::TryNew;
    ///
    /// let result = PositiveSize::try_new(0);
    ///
    /// match result {
    ///     Err(ErrorsPositiveInt::ZeroValue { backtrace }) => {
    ///         println!("Error: Zero is not a valid positive size");
    ///         println!("Backtrace:\n{}", backtrace);
    ///     }
    ///     Ok(_) => unreachable!("Zero should fail"),
    /// }
    /// ```
    #[error("The input value is zero (it must be strictly positive")]
    ZeroValue {
        /// Stack backtrace captured at the error creation site.
        ///
        /// Useful for tracing the origin of zero values in complex computational flows.
        backtrace: Backtrace,
    },
}

#[duplicate_item(
    T                      docstring;
    [PositiveSize]         ["Type indicating a ***positive*** size. It is basically a [`usize`] that cannot have a value smaller than 1"];
    [NumIntervals]         ["Type indicating a ***positive*** number of intervals. It is basically a [`usize`] that cannot have a value smaller than 1"];
    [PositiveNumPoints1D]  ["Type indicating a ***positive*** number of 1D points. It is basically a [`usize`] that cannot have a value smaller than 1"];
)]
#[derive(
    Debug,
    Clone,
    Copy,
    PartialEq,
    Eq,
    PartialOrd,
    Ord,
    Display,
    AsRef,
    Hash,
    Serialize,
    Deserialize,
    IntoInner,
)]
#[doc = docstring]
pub struct T(usize);

#[duplicate_item(
    T;
    [PositiveSize];
    [NumIntervals];
    [PositiveNumPoints1D];
)]
impl TryNew for T {
    type Error = ErrorsPositiveInt;

    fn try_new(value: usize) -> Result<Self, Self::Error> {
        if value == 0 {
            Err(ErrorsPositiveInt::ZeroValue {
                backtrace: capture_backtrace(),
            })
        } else {
            Ok(Self(value))
        }
    }
}

//------------------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------
#[nutype(derive(
    Debug,
    Clone,
    Copy,
    PartialEq,
    Eq,
    PartialOrd,
    Ord,
    Display,
    AsRef,
    Hash,
    Serialize,
    Deserialize
))]
/// Type indicating the ID of an interval.
pub struct IntervalId(usize);
//----------------------------------------------------------------------------------------------

//-----------------------------------------------------------------------------------

/// A wrapper type for real numbers that implements [`Hash`] and [`Eq`].
///
/// This type wraps a [`RealScalar`] value and provides [`Hash`] and [`Eq`] implementations,
/// enabling real numbers to be used as hash map keys or in hash sets. The hashing is based
/// on the raw bit representation of the floating-point value.
///
/// # Restrictions
///
/// Values must be finite (not NaN or infinite). This is enforced via debug assertion.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(bound(deserialize = "RealType: for<'a> Deserialize<'a>"))]
pub struct HashableScalar<RealType: RealScalar> {
    value: RealType,
}

impl<RealType: RealScalar> Eq for HashableScalar<RealType> {}

impl<RealType: RealScalar> HashableScalar<RealType> {
    /// Creates a new hashable real number from a finite value.
    ///
    /// # Panics (Debug Mode)
    ///
    /// Panics in debug mode if the value is not finite (NaN or infinite).
    pub fn new(value: RealType) -> Self {
        debug_assert!(
            value.is_finite(),
            "HashableScalar can only be constructed from finite real values!"
        );
        HashableScalar { value }
    }
}

impl<RealType: RealScalar> Hash for HashableScalar<RealType> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.value.as_raw_ref().compute_hash(state);
    }
}
//-----------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------------------

#[cfg(test)]
mod tests {
    use super::*;

    mod interval_id {
        use super::*;

        #[test]
        fn new() {
            // Test creating an IntervalId instance with a value of 0
            let v = IntervalId::new(0);
            assert_eq!(*v.as_ref(), 0);

            // Test creating an IntervalId instance with a positive value
            let v = IntervalId::new(5);
            assert_eq!(*v.as_ref(), 5);
        }

        #[test]
        fn equality_operator() {
            // Test equality operator for IntervalId instances
            let a = IntervalId::new(0);
            let b = IntervalId::new(0);
            assert!(a == b);

            let c = IntervalId::new(5);
            let d = IntervalId::new(5);
            assert!(c == d);
        }

        #[test]
        fn inequality_operator() {
            // Test inequality operator for IntervalId instances
            let a = IntervalId::new(0);
            let b = IntervalId::new(1);
            assert!(a != b);

            let c = IntervalId::new(5);
            let d = IntervalId::new(10);
            assert!(c != d);
        }

        #[test]
        fn debug_trait() {
            // Test the Debug trait
            let id = IntervalId::new(3);
            assert_eq!(format!("{:?}", id), "IntervalId(3)");
        }

        #[test]
        #[allow(clippy::clone_on_copy)]
        fn clone_trait() {
            // Test the Clone trait
            let id = IntervalId::new(4);
            let cloned_id = id.clone();
            assert_eq!(id, cloned_id);
        }

        #[test]
        fn copy_trait() {
            // Test the Copy trait
            let id = IntervalId::new(2);
            let copied_id = id;
            assert_eq!(id, copied_id);
        }

        #[test]
        fn partial_eq_trait() {
            // Test the PartialEq trait
            let id1 = IntervalId::new(6);
            let id2 = IntervalId::new(6);
            assert_eq!(id1, id2);
        }

        #[test]
        fn partial_ord_trait() {
            // Test the PartialOrd trait
            let id1 = IntervalId::new(3);
            let id2 = IntervalId::new(5);
            assert!(id1 < id2);
        }

        #[test]
        fn display_trait() {
            // Test the Display trait
            let id = IntervalId::new(7);
            assert_eq!(format!("{}", id), "7");
        }

        #[test]
        fn as_ref_trait() {
            // Test the AsRef trait
            let id = IntervalId::new(8);
            let inner: &usize = id.as_ref();
            assert_eq!(*inner, 8);
        }

        #[test]
        fn hash_trait() {
            // Test the Hash trait
            use std::collections::hash_map::DefaultHasher;
            use std::hash::{Hash, Hasher};

            let id = IntervalId::new(9);
            let mut hasher = DefaultHasher::new();
            id.hash(&mut hasher);
            let hash = hasher.finish();

            let mut hasher2 = DefaultHasher::new();
            id.hash(&mut hasher2);
            let hash2 = hasher2.finish();

            assert_eq!(hash, hash2);
        }

        #[test]
        fn serialize_deserialize() {
            // Test the Serialize and Deserialize traits
            let id = IntervalId::new(10);
            let serialized = serde_json::to_string(&id).unwrap();
            let deserialized: IntervalId = serde_json::from_str(&serialized).unwrap();
            assert_eq!(id, deserialized);
        }
    }

    mod num_intervals {
        use super::*;

        #[test]
        fn try_new() {
            // Test creating a valid NumIntervals instance
            let v = NumIntervals::try_new(1).unwrap();
            assert_eq!(*v.as_ref(), 1);

            // Test creating a valid NumIntervals instance with a positive value
            let v = NumIntervals::try_new(5).unwrap();
            assert_eq!(*v.as_ref(), 5);

            // Test creating an invalid NumIntervals instance with a value of 0
            let v = NumIntervals::try_new(0);
            assert!(v.is_err());
        }

        #[test]
        fn from_positive_size() {
            // Test creating a NumIntervals instance from a PositiveSize instance
            let pos_size = PositiveSize::try_new(5).unwrap();
            let num_intervals = NumIntervals::from(pos_size);
            assert_eq!(*num_intervals.as_ref(), 5);
        }

        #[test]
        fn equality_operator() {
            // Test equality operator for NumIntervals instances
            let a = NumIntervals::try_new(1).unwrap();
            let b = NumIntervals::try_new(1).unwrap();
            assert!(a == b);

            let c = NumIntervals::try_new(5).unwrap();
            let d = NumIntervals::try_new(5).unwrap();
            assert!(c == d);
        }

        #[test]
        fn inequality_operator() {
            // Test inequality operator for NumIntervals instances
            let a = NumIntervals::try_new(1).unwrap();
            let b = NumIntervals::try_new(2).unwrap();
            assert!(a != b);

            let c = NumIntervals::try_new(5).unwrap();
            let d = NumIntervals::try_new(10).unwrap();
            assert!(c != d);
        }

        #[test]
        fn debug_trait() {
            // Test the Debug trait
            let num_intervals = NumIntervals::try_new(3).unwrap();
            assert_eq!(format!("{:?}", num_intervals), "NumIntervals(3)");
        }

        #[test]
        #[allow(clippy::clone_on_copy)]
        fn clone_trait() {
            // Test the Clone trait
            let num_intervals = NumIntervals::try_new(4).unwrap();
            let cloned_num_intervals = num_intervals.clone();
            assert_eq!(num_intervals, cloned_num_intervals);
        }

        #[test]
        fn copy_trait() {
            // Test the Copy trait
            let num_intervals = NumIntervals::try_new(2).unwrap();
            let copied_num_intervals = num_intervals;
            assert_eq!(num_intervals, copied_num_intervals);
        }

        #[test]
        fn partial_eq_trait() {
            // Test the PartialEq trait
            let num_intervals1 = NumIntervals::try_new(6).unwrap();
            let num_intervals2 = NumIntervals::try_new(6).unwrap();
            assert_eq!(num_intervals1, num_intervals2);
        }

        #[test]
        fn partial_ord_trait() {
            // Test the PartialOrd trait
            let num_intervals1 = NumIntervals::try_new(3).unwrap();
            let num_intervals2 = NumIntervals::try_new(5).unwrap();
            assert!(num_intervals1 < num_intervals2);
        }

        #[test]
        fn display_trait() {
            // Test the Display trait
            let num_intervals = NumIntervals::try_new(7).unwrap();
            assert_eq!(format!("{}", num_intervals), "7");
        }

        #[test]
        fn as_ref_trait() {
            // Test the AsRef trait
            let num_intervals = NumIntervals::try_new(8).unwrap();
            let inner: &usize = num_intervals.as_ref();
            assert_eq!(*inner, 8);
        }

        #[test]
        fn hash_trait() {
            // Test the Hash trait
            use std::collections::hash_map::DefaultHasher;
            use std::hash::{Hash, Hasher};

            let num_intervals = NumIntervals::try_new(9).unwrap();
            let mut hasher = DefaultHasher::new();
            num_intervals.hash(&mut hasher);
            let hash = hasher.finish();

            let mut hasher2 = DefaultHasher::new();
            num_intervals.hash(&mut hasher2);
            let hash2 = hasher2.finish();

            assert_eq!(hash, hash2);
        }

        #[test]
        fn serialize_deserialize() {
            // Test the Serialize and Deserialize traits
            let num_intervals = NumIntervals::try_new(10).unwrap();
            let serialized = serde_json::to_string(&num_intervals).unwrap();
            let deserialized: NumIntervals = serde_json::from_str(&serialized).unwrap();
            assert_eq!(num_intervals, deserialized);
        }
    }

    mod positive_num_points_1d {
        use super::*;

        #[test]
        fn try_new() {
            // Test creating a valid PositiveNumPoints1D instance
            let v = PositiveNumPoints1D::try_new(1).unwrap();
            assert_eq!(*v.as_ref(), 1);

            // Test creating a valid PositiveNumPoints1D instance with a positive value
            let v = PositiveNumPoints1D::try_new(5).unwrap();
            assert_eq!(*v.as_ref(), 5);

            // Test creating an invalid PositiveNumPoints1D instance with a value of 0
            let v = PositiveNumPoints1D::try_new(0);
            assert!(v.is_err());
        }

        #[test]
        fn equality_operator() {
            // Test equality operator for PositiveNumPoints1D instances
            let a = PositiveNumPoints1D::try_new(1).unwrap();
            let b = PositiveNumPoints1D::try_new(1).unwrap();
            assert!(a == b);

            let c = PositiveNumPoints1D::try_new(5).unwrap();
            let d = PositiveNumPoints1D::try_new(5).unwrap();
            assert!(c == d);
        }

        #[test]
        fn inequality_operator() {
            // Test inequality operator for PositiveNumPoints1D instances
            let a = PositiveNumPoints1D::try_new(1).unwrap();
            let b = PositiveNumPoints1D::try_new(2).unwrap();
            assert!(a != b);

            let c = PositiveNumPoints1D::try_new(5).unwrap();
            let d = PositiveNumPoints1D::try_new(10).unwrap();
            assert!(c != d);
        }

        #[test]
        fn debug_trait() {
            // Test the Debug trait
            let num_points = PositiveNumPoints1D::try_new(3).unwrap();
            assert_eq!(format!("{:?}", num_points), "PositiveNumPoints1D(3)");
        }

        #[test]
        #[allow(clippy::clone_on_copy)]
        fn clone_trait() {
            // Test the Clone trait
            let num_points = PositiveNumPoints1D::try_new(4).unwrap();
            let cloned_num_points = num_points.clone();
            assert_eq!(num_points, cloned_num_points);
        }

        #[test]
        fn copy_trait() {
            // Test the Copy trait
            let num_points = PositiveNumPoints1D::try_new(2).unwrap();
            let copied_num_points = num_points;
            assert_eq!(num_points, copied_num_points);
        }

        #[test]
        fn partial_eq_trait() {
            // Test the PartialEq trait
            let num_points1 = PositiveNumPoints1D::try_new(6).unwrap();
            let num_points2 = PositiveNumPoints1D::try_new(6).unwrap();
            assert_eq!(num_points1, num_points2);
        }

        #[test]
        fn partial_ord_trait() {
            // Test the PartialOrd trait
            let num_points1 = PositiveNumPoints1D::try_new(3).unwrap();
            let num_points2 = PositiveNumPoints1D::try_new(5).unwrap();
            assert!(num_points1 < num_points2);
        }

        #[test]
        fn display_trait() {
            // Test the Display trait
            let num_points = PositiveNumPoints1D::try_new(7).unwrap();
            assert_eq!(format!("{}", num_points), "7");
        }

        #[test]
        fn as_ref_trait() {
            // Test the AsRef trait
            let num_points = PositiveNumPoints1D::try_new(8).unwrap();
            let inner: &usize = num_points.as_ref();
            assert_eq!(*inner, 8);
        }

        #[test]
        fn hash_trait() {
            // Test the Hash trait
            use std::collections::hash_map::DefaultHasher;
            use std::hash::{Hash, Hasher};

            let num_points = PositiveNumPoints1D::try_new(9).unwrap();
            let mut hasher = DefaultHasher::new();
            num_points.hash(&mut hasher);
            let hash = hasher.finish();

            let mut hasher2 = DefaultHasher::new();
            num_points.hash(&mut hasher2);
            let hash2 = hasher2.finish();

            assert_eq!(hash, hash2);
        }

        #[test]
        fn serialize_deserialize() {
            // Test the Serialize and Deserialize traits
            let num_points = PositiveNumPoints1D::try_new(10).unwrap();
            let serialized = serde_json::to_string(&num_points).unwrap();
            let deserialized: PositiveNumPoints1D = serde_json::from_str(&serialized).unwrap();
            assert_eq!(num_points, deserialized);
        }
    }

    mod positive_size {
        use super::*;

        #[test]
        fn try_new() {
            // Test creating a valid PositiveSize instance
            let v = PositiveSize::try_new(1).unwrap();
            assert_eq!(*v.as_ref(), 1);

            // Test creating a valid PositiveSize instance with a positive value
            let v = PositiveSize::try_new(5).unwrap();
            assert_eq!(*v.as_ref(), 5);

            // Test creating an invalid PositiveSize instance with a value of 0
            let v = PositiveSize::try_new(0);
            assert!(v.is_err());
        }

        #[test]
        fn try_from_size() {
            // Test creating a PositiveSize instance from a Size instance
            let size = Size::new(5);
            let pos_size = PositiveSize::try_from(size).unwrap();
            assert_eq!(*pos_size.as_ref(), 5);

            // Test creating a PositiveSize instance from a Size instance with value 0
            let size_zero = Size::new(0);
            let pos_size_zero = PositiveSize::try_from(size_zero);
            assert!(pos_size_zero.is_err());
        }

        #[test]
        fn equality_operator() {
            // Test equality operator for PositiveSize instances
            let a = PositiveSize::try_new(1).unwrap();
            let b = PositiveSize::try_new(1).unwrap();
            assert!(a == b);

            let c = PositiveSize::try_new(5).unwrap();
            let d = PositiveSize::try_new(5).unwrap();
            assert!(c == d);
        }

        #[test]
        fn inequality_operator() {
            // Test inequality operator for PositiveSize instances
            let a = PositiveSize::try_new(1).unwrap();
            let b = PositiveSize::try_new(2).unwrap();
            assert!(a != b);

            let c = PositiveSize::try_new(5).unwrap();
            let d = PositiveSize::try_new(10).unwrap();
            assert!(c != d);
        }

        #[test]
        fn debug_trait() {
            // Test the Debug trait
            let size = PositiveSize::try_new(3).unwrap();
            assert_eq!(format!("{:?}", size), "PositiveSize(3)");
        }

        #[test]
        #[allow(clippy::clone_on_copy)]
        fn clone_trait() {
            // Test the Clone trait
            let size = PositiveSize::try_new(4).unwrap();
            let cloned_size = size.clone();
            assert_eq!(size, cloned_size);
        }

        #[test]
        fn copy_trait() {
            // Test the Copy trait
            let size = PositiveSize::try_new(2).unwrap();
            let copied_size = size;
            assert_eq!(size, copied_size);
        }

        #[test]
        fn partial_eq_trait() {
            // Test the PartialEq trait
            let size1 = PositiveSize::try_new(6).unwrap();
            let size2 = PositiveSize::try_new(6).unwrap();
            assert_eq!(size1, size2);
        }

        #[test]
        fn partial_ord_trait() {
            // Test the PartialOrd trait
            let size1 = PositiveSize::try_new(3).unwrap();
            let size2 = PositiveSize::try_new(5).unwrap();
            assert!(size1 < size2);
        }

        #[test]
        fn display_trait() {
            // Test the Display trait
            let size = PositiveSize::try_new(7).unwrap();
            assert_eq!(format!("{}", size), "7");
        }

        #[test]
        fn as_ref_trait() {
            // Test the AsRef trait
            let size = PositiveSize::try_new(8).unwrap();
            let inner: &usize = size.as_ref();
            assert_eq!(*inner, 8);
        }

        #[test]
        fn hash_trait() {
            // Test the Hash trait
            use std::collections::hash_map::DefaultHasher;
            use std::hash::{Hash, Hasher};

            let size = PositiveSize::try_new(9).unwrap();
            let mut hasher = DefaultHasher::new();
            size.hash(&mut hasher);
            let hash = hasher.finish();

            let mut hasher2 = DefaultHasher::new();
            size.hash(&mut hasher2);
            let hash2 = hasher2.finish();

            assert_eq!(hash, hash2);
        }

        #[test]
        fn serialize_deserialize() {
            // Test the Serialize and Deserialize traits
            let size = PositiveSize::try_new(10).unwrap();
            let serialized = serde_json::to_string(&size).unwrap();
            let deserialized: PositiveSize = serde_json::from_str(&serialized).unwrap();
            assert_eq!(size, deserialized);
        }
    }

    mod size {
        use super::*;

        #[test]
        fn new() {
            // Test creating a Size instance with a value of 0
            let v = Size::new(0);
            assert_eq!(*v.as_ref(), 0);

            // Test creating a Size instance with a positive value
            let v = Size::new(5);
            assert_eq!(*v.as_ref(), 5);
        }

        #[test]
        fn equality_operator() {
            // Test equality operator for Size instances
            let a = Size::new(0);
            let b = Size::new(0);
            assert!(a == b);

            let c = Size::new(5);
            let d = Size::new(5);
            assert!(c == d);
        }

        #[test]
        fn inequality_operator() {
            // Test inequality operator for Size instances
            let a = Size::new(0);
            let b = Size::new(1);
            assert!(a != b);

            let c = Size::new(5);
            let d = Size::new(10);
            assert!(c != d);
        }

        #[test]
        fn debug_trait() {
            // Test the Debug trait
            let size = Size::new(3);
            assert_eq!(format!("{:?}", size), "Size(3)");
        }

        #[test]
        #[allow(clippy::clone_on_copy)]
        fn clone_trait() {
            // Test the Clone trait
            let size = Size::new(4);

            let cloned_size = size.clone();
            assert_eq!(size, cloned_size);
        }

        #[test]
        fn copy_trait() {
            // Test the Copy trait
            let size = Size::new(2);
            let copied_size = size;
            assert_eq!(size, copied_size);
        }

        #[test]
        fn partial_eq_trait() {
            // Test the PartialEq trait
            let size1 = Size::new(6);
            let size2 = Size::new(6);
            assert_eq!(size1, size2);
        }

        #[test]
        fn partial_ord_trait() {
            // Test the PartialOrd trait
            let size1 = Size::new(3);
            let size2 = Size::new(5);
            assert!(size1 < size2);
        }

        #[test]
        fn display_trait() {
            // Test the Display trait
            let size = Size::new(7);
            assert_eq!(format!("{}", size), "7");
        }

        #[test]
        fn as_ref_trait() {
            // Test the AsRef trait
            let size = Size::new(8);
            let inner: &usize = size.as_ref();
            assert_eq!(*inner, 8);
        }

        #[test]
        fn hash_trait() {
            // Test the Hash trait
            use std::collections::hash_map::DefaultHasher;
            use std::hash::{Hash, Hasher};

            let size = Size::new(9);
            let mut hasher = DefaultHasher::new();
            size.hash(&mut hasher);
            let hash = hasher.finish();

            let mut hasher2 = DefaultHasher::new();
            size.hash(&mut hasher2);
            let hash2 = hasher2.finish();

            assert_eq!(hash, hash2);
        }

        #[test]
        fn serialize_deserialize() {
            // Test the Serialize and Deserialize traits
            let size = Size::new(10);
            let serialized = serde_json::to_string(&size).unwrap();
            let deserialized: Size = serde_json::from_str(&serialized).unwrap();
            assert_eq!(size, deserialized);
        }

        #[test]
        fn from_positive_size() {
            // Test creating a Size instance from a PositiveSize instance
            let pos_size = PositiveSize::try_new(5).unwrap();
            let size = Size::from(pos_size);
            assert_eq!(*size.as_ref(), 5);
        }
    }
}
//------------------------------------------------------------------------------------------------------------
