diff --git a/src/lib.rs b/src/lib.rs index de81be3..a68379d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,12 +52,42 @@ impl<'de> Deserialize<'de> for SourceFile { /// e.g. gcc @compile_flags.txt. Because the `CompileCommand` struct is used to /// represent both file types, we utilize a tagged union here to differentitate /// between the two files -#[derive(Debug, Clone, Deserialize)] +#[derive(Debug, Clone, Hash, Eq, PartialEq)] pub enum CompileArgs { Arguments(Vec), Flags(Vec), } +impl<'de> Deserialize<'de> for CompileArgs { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + #[allow(dead_code)] + struct CompileArgVisitor; + + impl<'de> Visitor<'de> for CompileArgVisitor { + type Value = CompileArgs; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string representing a file path") + } + + fn visit_str(self, value: &str) -> Result + where + E: SerdeError, + { + Ok(CompileArgs::Arguments(())) + } + } + + match serde_json::Value::deserialize(deserializer)? { + serde_json::Value::String(s) => Ok(SourceFile::File(PathBuf::from(s))), + _ => Err(SerdeError::custom("expected a string")), + } + } +} + /// Represents a single entry within a `compile_commands.json` file, or a compile_flags.txt file /// Either `arguments` or `command` is required. `arguments` is preferred, as shell (un)escaping /// is a possible source of errors.