lex_core/lex/ast/elements/parameter.rs
1//! Parameter element
2//!
3//! A parameter is a pair of key and value. Parameters are components that carry a bit
4//! of information inside an element, only used in metadata. They can be used in
5//! annotations and verbatim blocks to convey structured metadata.
6//!
7//! Together with labels, parameters allow for structured metadata. They are used in
8//! data nodes, which have the syntax:
9//! :: label params?
10//!
11//! Syntax
12//!
13//! <key> "=" <value>
14//!
15//! Examples:
16//! priority=high
17//! severity=high
18//!
19//! Parameters are optional in data nodes. Multiple parameters can be specified
20//! separated by whitespace.
21//!
22//! See [Data](super::data::Data) for how parameters are used in data nodes.
23//!
24//! Learn More:
25//! - Parameters spec: specs/v1/elements/parameter.lex
26
27use super::super::range::{Position, Range};
28use crate::lex::escape::unescape_quoted;
29use std::fmt;
30
31/// A parameter represents a key-value pair
32#[derive(Debug, Clone, PartialEq)]
33pub struct Parameter {
34 pub key: String,
35 pub value: String,
36 pub location: Range,
37}
38
39impl Parameter {
40 fn default_location() -> Range {
41 Range::new(0..0, Position::new(0, 0), Position::new(0, 0))
42 }
43
44 pub fn new(key: String, value: String) -> Self {
45 Self {
46 key,
47 value,
48 location: Self::default_location(),
49 }
50 }
51
52 /// Preferred builder
53 pub fn at(mut self, location: Range) -> Self {
54 self.location = location;
55 self
56 }
57
58 /// Returns the semantic value with outer quotes stripped and escapes resolved.
59 ///
60 /// For quoted values like `"Hello World"`, returns `Hello World`.
61 /// For values with escapes like `"say \"hello\""`, returns `say "hello"`.
62 /// For unquoted values like `simple`, returns `simple` unchanged.
63 pub fn unquoted_value(&self) -> String {
64 unescape_quoted(&self.value)
65 }
66}
67
68impl fmt::Display for Parameter {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(f, "{}={}", self.key, self.value)
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn test_parameter() {
80 let location = super::super::super::range::Range::new(
81 0..0,
82 super::super::super::range::Position::new(1, 0),
83 super::super::super::range::Position::new(1, 10),
84 );
85 let param = Parameter::new("key".to_string(), "value".to_string()).at(location.clone());
86 assert_eq!(param.location, location);
87 }
88}