diff --git a/crates/weaver_semconv/src/attribute.rs b/crates/weaver_semconv/src/attribute.rs index d88954ad..c6fd215d 100644 --- a/crates/weaver_semconv/src/attribute.rs +++ b/crates/weaver_semconv/src/attribute.rs @@ -410,6 +410,14 @@ pub enum Examples { Bools(Vec), /// A array of strings example. Strings(Vec), + /// List of arrays of integers example. + ListOfInts(Vec>), + /// List of arrays of doubles example. + ListOfDoubles(Vec>>), + /// List of arrays of bools example. + ListOfBools(Vec>), + /// List of arrays of strings example. + ListOfStrings(Vec>), } /// The different requirement level specifications. @@ -772,6 +780,154 @@ mod tests { assert_eq!(attr.tag(), Some("tag".to_owned())); assert!(attr.is_required()); } + + #[test] + fn test_examples_bool() { + let yaml = "---\ntrue"; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!(ex, Examples::Bool(true)); + } + + #[test] + fn test_examples_int() { + let yaml = "---\n42"; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!(ex, Examples::Int(42)); + } + + #[test] + fn test_examples_double() { + let yaml = "---\n3.15"; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!(ex, Examples::Double(OrderedFloat(3.15))); + } + + #[test] + fn test_examples_string() { + let yaml = "---\n\"foo\""; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!(ex, Examples::String("foo".to_owned())); + } + + #[test] + fn test_examples_strings() { + let yaml = "---\n- \"foo\"\n- \"bar\""; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!( + ex, + Examples::Strings(vec!["foo".to_owned(), "bar".to_owned()]) + ); + } + + #[test] + fn test_examples_ints() { + let yaml = "---\n- 42\n- 43"; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!(ex, Examples::Ints(vec![42, 43])); + } + + #[test] + fn test_examples_doubles() { + let yaml = "---\n- 3.15\n- 2.71"; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!( + ex, + Examples::Doubles(vec![OrderedFloat(3.15), OrderedFloat(2.71)]) + ); + } + + #[test] + fn test_examples_bools() { + let yaml = "---\n- true\n- false"; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!(ex, Examples::Bools(vec![true, false])); + } + + #[test] + fn test_examples_list_of_ints() { + let yaml = "---\n- [42, 43]\n- [44, 45]"; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!(ex, Examples::ListOfInts(vec![vec![42, 43], vec![44, 45]])); + } + + #[test] + fn test_examples_list_of_doubles() { + let yaml = "---\n- [3.15, 2.71]\n- [1.41, 1.61]"; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!( + ex, + Examples::ListOfDoubles(vec![ + vec![OrderedFloat(3.15), OrderedFloat(2.71)], + vec![OrderedFloat(1.41), OrderedFloat(1.61)] + ]) + ); + } + + #[test] + fn test_examples_list_of_bools() { + let yaml = "---\n- [true, false]\n- [false, true]"; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!( + ex, + Examples::ListOfBools(vec![vec![true, false], vec![false, true]]) + ); + } + + #[test] + fn test_examples_list_of_strings() { + let yaml = "---\n- [\"foo\", \"bar\"]\n- [\"baz\", \"qux\"]"; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!( + ex, + Examples::ListOfStrings(vec![ + vec!["foo".to_owned(), "bar".to_owned()], + vec!["baz".to_owned(), "qux".to_owned()] + ]) + ); + } + + #[test] + fn test_examples_list_of_ints_array_style() { + let yaml = "[ [42, 43], [44, 45] ]"; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!(ex, Examples::ListOfInts(vec![vec![42, 43], vec![44, 45]])); + } + + #[test] + fn test_examples_list_of_doubles_array_style() { + let yaml = "[ [3.15, 2.71], [1.41, 1.61] ]"; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!( + ex, + Examples::ListOfDoubles(vec![ + vec![OrderedFloat(3.15), OrderedFloat(2.71)], + vec![OrderedFloat(1.41), OrderedFloat(1.61)] + ]) + ); + } + + #[test] + fn test_examples_list_of_bools_array_style() { + let yaml = "[ [true, false], [false, true] ]"; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!( + ex, + Examples::ListOfBools(vec![vec![true, false], vec![false, true]]) + ); + } + + #[test] + fn test_examples_list_of_strings_array_style() { + let yaml = "[ [\"foo\", \"bar\"], [\"baz\", \"qux\"] ]"; + let ex: Examples = serde_yaml::from_str(yaml).unwrap(); + assert_eq!( + ex, + Examples::ListOfStrings(vec![ + vec!["foo".to_owned(), "bar".to_owned()], + vec!["baz".to_owned(), "qux".to_owned()] + ]) + ); + } } /// An attribute definition with its provenance (path or URL). diff --git a/crates/weaver_semconv_gen/src/gen.rs b/crates/weaver_semconv_gen/src/gen.rs index c1c86a1a..5b9ce38e 100644 --- a/crates/weaver_semconv_gen/src/gen.rs +++ b/crates/weaver_semconv_gen/src/gen.rs @@ -58,10 +58,15 @@ fn enum_type_string(members: &[EnumEntriesSpec]) -> &'static str { } } -fn write_example_list( +fn write_example_list( out: &mut Out, list: &[Element], + is_array: bool, ) -> Result<(), Error> { + if is_array { + write!(out, "`{:?}`", list)?; + return Ok(()); + } let mut first = true; for e in list { if !first { @@ -73,16 +78,40 @@ fn write_example_list( Ok(()) } -fn write_examples_string(out: &mut Out, examples: &Examples) -> Result<(), Error> { +fn write_example_list_of_lists( + out: &mut Out, + list: &[Vec], + is_array: bool, +) -> Result<(), Error> { + let mut first = true; + for e in list { + if !first { + write!(out, "; ")?; + } + write_example_list(out, e, is_array)?; + first = false; + } + Ok(()) +} + +fn write_examples_string( + out: &mut Out, + examples: &Examples, + is_array: bool, +) -> Result<(), Error> { match examples { Examples::Bool(value) => Ok(write!(out, "`{value}`")?), Examples::Int(value) => Ok(write!(out, "`{value}`")?), Examples::Double(value) => Ok(write!(out, "`{value}`")?), Examples::String(value) => Ok(write!(out, "`{value}`")?), - Examples::Ints(values) => write_example_list(out, values), - Examples::Doubles(values) => write_example_list(out, values), - Examples::Bools(values) => write_example_list(out, values), - Examples::Strings(values) => write_example_list(out, values), + Examples::Ints(values) => write_example_list(out, values, is_array), + Examples::Doubles(values) => write_example_list(out, values, is_array), + Examples::Bools(values) => write_example_list(out, values, is_array), + Examples::Strings(values) => write_example_list(out, values, is_array), + Examples::ListOfInts(values) => write_example_list_of_lists(out, values, is_array), + Examples::ListOfDoubles(values) => write_example_list_of_lists(out, values, is_array), + Examples::ListOfBools(values) => write_example_list_of_lists(out, values, is_array), + Examples::ListOfStrings(values) => write_example_list_of_lists(out, values, is_array), } } @@ -183,6 +212,16 @@ impl<'a> AttributeView<'a> { matches!(&self.attribute.r#type, AttributeType::Enum { .. }) } + fn is_array(&self) -> bool { + matches!( + &self.attribute.r#type, + AttributeType::PrimitiveOrArray(PrimitiveOrArrayTypeSpec::Booleans) + | AttributeType::PrimitiveOrArray(PrimitiveOrArrayTypeSpec::Ints) + | AttributeType::PrimitiveOrArray(PrimitiveOrArrayTypeSpec::Doubles) + | AttributeType::PrimitiveOrArray(PrimitiveOrArrayTypeSpec::Strings) + ) + } + fn is_sampling_relevant(&self) -> bool { self.attribute.sampling_relevant.unwrap_or(false) } @@ -307,7 +346,7 @@ impl<'a> AttributeView<'a> { fn write_examples(&self, out: &mut Out) -> Result<(), Error> { match &self.attribute.examples { - Some(examples) => write_examples_string(out, examples), + Some(examples) => write_examples_string(out, examples, self.is_array()), None => // Enums can pull examples from the enum if not otherwise specified. {