Skip to main content

nu_command/semver/
range.rs

1use nu_protocol::{ShellError, Span, Value};
2use serde::{Deserialize, Serialize};
3use std::any::Any;
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct SemverRangeValue {
7    pub requirement: semver::VersionReq,
8}
9
10#[typetag::serde]
11impl nu_protocol::CustomValue for SemverRangeValue {
12    fn clone_value(&self, span: Span) -> Value {
13        Value::custom(Box::new(self.clone()), span)
14    }
15
16    fn type_name(&self) -> String {
17        "semver-range".to_string()
18    }
19
20    fn to_base_value(&self, span: Span) -> Result<Value, ShellError> {
21        Ok(Value::string(self.requirement.to_string(), span))
22    }
23
24    fn as_any(&self) -> &dyn Any {
25        self
26    }
27
28    fn as_mut_any(&mut self) -> &mut dyn Any {
29        self
30    }
31}
32
33impl SemverRangeValue {
34    pub fn new(requirement: semver::VersionReq) -> Self {
35        Self { requirement }
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42    use nu_protocol::CustomValue;
43
44    #[test]
45    fn test_new() {
46        let req = semver::VersionReq::parse(">=1.0.0").unwrap();
47        let range = SemverRangeValue::new(req.clone());
48        assert_eq!(range.requirement.to_string(), ">=1.0.0");
49    }
50
51    #[test]
52    fn test_custom_value_trait() {
53        let req = semver::VersionReq::parse("^1.2.3").unwrap();
54        let range = SemverRangeValue::new(req);
55
56        // Test type_name
57        assert_eq!(range.type_name(), "semver-range");
58
59        // Test to_base_value
60        let base = range.to_base_value(Span::test_data()).unwrap();
61        assert!(matches!(base, Value::String { val, .. } if val == "^1.2.3"));
62
63        // Test clone_value
64        let cloned = range.clone_value(Span::test_data());
65        assert!(matches!(cloned, Value::Custom { .. }));
66
67        // Test as_any
68        let any = range.as_any();
69        assert!(any.downcast_ref::<SemverRangeValue>().is_some());
70    }
71
72    #[test]
73    fn test_various_requirements() {
74        let test_cases = vec![
75            ">=1.0.0",
76            "<2.0.0",
77            ">=1.0.0, <2.0.0",
78            "^1.2.3",
79            "~1.2",
80            "1.2.3",
81            "*",
82        ];
83
84        for req_str in test_cases {
85            let req = semver::VersionReq::parse(req_str).unwrap();
86            let range = SemverRangeValue::new(req);
87            assert_eq!(range.type_name(), "semver-range");
88        }
89    }
90}