Commit c6945aca authored by Matthew Maurer's avatar Matthew Maurer Committed by Miguel Ojeda

rust: support arrays in target JSON

Some configuration options such as the supported sanitizer list are
arrays. To support using Rust with sanitizers on x86, we must update the
target.json generator to support this case.

The Push trait is removed in favor of the From trait because the Push
trait doesn't work well in the nested case where you are not really
pushing values to a TargetSpec.
Signed-off-by: default avatarMatthew Maurer <mmaurer@google.com>
Signed-off-by: default avatarAlice Ryhl <aliceryhl@google.com>
Reviewed-by: default avatarGary Guo <gary@garyguo.net>
Tested-by: default avatarGatlin Newhouse <gatlin.newhouse@gmail.com>
Link: https://lore.kernel.org/r/20240730-target-json-arrays-v1-1-2b376fd0ecf4@google.comSigned-off-by: default avatarMiguel Ojeda <ojeda@kernel.org>
parent 6d1c22d0
...@@ -20,12 +20,28 @@ enum Value { ...@@ -20,12 +20,28 @@ enum Value {
Boolean(bool), Boolean(bool),
Number(i32), Number(i32),
String(String), String(String),
Array(Vec<Value>),
Object(Object), Object(Object),
} }
type Object = Vec<(String, Value)>; type Object = Vec<(String, Value)>;
/// Minimal "almost JSON" generator (e.g. no `null`s, no arrays, no escaping), fn comma_sep<T>(
seq: &[T],
formatter: &mut Formatter<'_>,
f: impl Fn(&mut Formatter<'_>, &T) -> Result,
) -> Result {
if let [ref rest @ .., ref last] = seq[..] {
for v in rest {
f(formatter, v)?;
formatter.write_str(",")?;
}
f(formatter, last)?;
}
Ok(())
}
/// Minimal "almost JSON" generator (e.g. no `null`s, no escaping),
/// enough for this purpose. /// enough for this purpose.
impl Display for Value { impl Display for Value {
fn fmt(&self, formatter: &mut Formatter<'_>) -> Result { fn fmt(&self, formatter: &mut Formatter<'_>) -> Result {
...@@ -33,59 +49,67 @@ fn fmt(&self, formatter: &mut Formatter<'_>) -> Result { ...@@ -33,59 +49,67 @@ fn fmt(&self, formatter: &mut Formatter<'_>) -> Result {
Value::Boolean(boolean) => write!(formatter, "{}", boolean), Value::Boolean(boolean) => write!(formatter, "{}", boolean),
Value::Number(number) => write!(formatter, "{}", number), Value::Number(number) => write!(formatter, "{}", number),
Value::String(string) => write!(formatter, "\"{}\"", string), Value::String(string) => write!(formatter, "\"{}\"", string),
Value::Array(values) => {
formatter.write_str("[")?;
comma_sep(&values[..], formatter, |formatter, v| v.fmt(formatter))?;
formatter.write_str("]")
}
Value::Object(object) => { Value::Object(object) => {
formatter.write_str("{")?; formatter.write_str("{")?;
if let [ref rest @ .., ref last] = object[..] { comma_sep(&object[..], formatter, |formatter, v| {
for (key, value) in rest { write!(formatter, "\"{}\": {}", v.0, v.1)
write!(formatter, "\"{}\": {},", key, value)?; })?;
}
write!(formatter, "\"{}\": {}", last.0, last.1)?;
}
formatter.write_str("}") formatter.write_str("}")
} }
} }
} }
} }
struct TargetSpec(Object); impl From<bool> for Value {
fn from(value: bool) -> Self {
impl TargetSpec { Self::Boolean(value)
fn new() -> TargetSpec {
TargetSpec(Vec::new())
} }
} }
trait Push<T> { impl From<i32> for Value {
fn push(&mut self, key: &str, value: T); fn from(value: i32) -> Self {
Self::Number(value)
}
} }
impl Push<bool> for TargetSpec { impl From<String> for Value {
fn push(&mut self, key: &str, value: bool) { fn from(value: String) -> Self {
self.0.push((key.to_string(), Value::Boolean(value))); Self::String(value)
} }
} }
impl Push<i32> for TargetSpec { impl From<&str> for Value {
fn push(&mut self, key: &str, value: i32) { fn from(value: &str) -> Self {
self.0.push((key.to_string(), Value::Number(value))); Self::String(value.to_string())
} }
} }
impl Push<String> for TargetSpec { impl From<Object> for Value {
fn push(&mut self, key: &str, value: String) { fn from(object: Object) -> Self {
self.0.push((key.to_string(), Value::String(value))); Self::Object(object)
} }
} }
impl Push<&str> for TargetSpec { impl<T: Into<Value>, const N: usize> From<[T; N]> for Value {
fn push(&mut self, key: &str, value: &str) { fn from(i: [T; N]) -> Self {
self.push(key, value.to_string()); Self::Array(i.into_iter().map(|v| v.into()).collect())
} }
} }
impl Push<Object> for TargetSpec { struct TargetSpec(Object);
fn push(&mut self, key: &str, value: Object) {
self.0.push((key.to_string(), Value::Object(value))); impl TargetSpec {
fn new() -> TargetSpec {
TargetSpec(Vec::new())
}
fn push(&mut self, key: &str, value: impl Into<Value>) {
self.0.push((key.to_string(), value.into()));
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment