Skip to main content

qubit_argument/argument/
argument_path.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//! Structured paths that identify arguments in validation errors.
9
10use std::fmt::{
11    self,
12    Display,
13    Formatter,
14};
15
16/// An owned path identifying an argument or one of its nested components.
17///
18/// The path is stored exactly as supplied; this type does not parse or
19/// normalize separators.
20#[derive(Debug, Clone, PartialEq, Eq, Hash)]
21pub struct ArgumentPath(String);
22
23impl ArgumentPath {
24    /// Creates an argument path by copying `path` without normalization.
25    ///
26    /// # Parameters
27    ///
28    /// - `path`: The path text to store.
29    ///
30    /// # Returns
31    ///
32    /// A new owned argument path.
33    #[inline]
34    pub fn new(path: &str) -> Self {
35        Self(path.to_owned())
36    }
37
38    /// Returns the stored path text.
39    ///
40    /// The returned string slice remains valid for the lifetime of this path.
41    #[inline]
42    pub fn as_str(&self) -> &str {
43        self.0.as_str()
44    }
45
46    /// Prepends a parent path component to this path.
47    ///
48    /// # Parameters
49    ///
50    /// - `prefix`: The parent path to place before the stored path.
51    ///
52    /// # Returns
53    ///
54    /// The composed path. Non-empty components are separated by one dot. If
55    /// either component is empty, no separator is added.
56    #[inline]
57    pub fn with_prefix(self, prefix: &str) -> Self {
58        if prefix.is_empty() {
59            return self;
60        }
61        if self.0.is_empty() {
62            return Self(prefix.to_owned());
63        }
64        let mut path = String::with_capacity(prefix.len() + 1 + self.0.len());
65        path.push_str(prefix);
66        path.push('.');
67        path.push_str(&self.0);
68        Self(path)
69    }
70}
71
72impl AsRef<str> for ArgumentPath {
73    /// Borrows the stored path as a string slice.
74    #[inline]
75    fn as_ref(&self) -> &str {
76        self.as_str()
77    }
78}
79
80impl Display for ArgumentPath {
81    /// Writes the stored path text without additional decoration.
82    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
83        formatter.write_str(self.as_str())
84    }
85}