blob: c8bf4bf5b9dcc818ce76e6fa494448989e4fd90d [file] [log] [blame]
use std::collections::BTreeSet;
use std::fmt;
use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer};
use serde::de::{Deserialize, Deserializer, MapAccess, SeqAccess, Visitor};
use serde::ser::{Serialize, SerializeStruct, Serializer};
#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub(crate) struct Glob {
pub(crate) allow_empty: bool,
pub(crate) include: BTreeSet<String>,
pub(crate) exclude: BTreeSet<String>,
}
impl Glob {
pub(crate) fn new_rust_srcs() -> Self {
Self {
allow_empty: false,
include: BTreeSet::from(["**/*.rs".to_owned()]),
exclude: BTreeSet::new(),
}
}
pub(crate) fn has_any_include(&self) -> bool {
self.include.is_empty()
// Note: self.exclude intentionally not considered. A glob is empty if
// there are no included globs. A glob cannot have only excludes.
}
}
impl Serialize for Glob {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let has_exclude = !self.exclude.is_empty();
let len = 2 + if has_exclude { 1 } else { 0 };
// Serialize as glob(allow_empty = False, include = [...], exclude = [...]).
let mut call = serializer.serialize_struct("glob", len)?;
call.serialize_field("allow_empty", &self.allow_empty)?;
call.serialize_field("include", &self.include)?;
if has_exclude {
call.serialize_field("exclude", &self.exclude)?;
}
call.end()
}
}
struct GlobVisitor;
impl<'de> Deserialize<'de> for Glob {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(GlobVisitor)
}
}
impl<'de> Visitor<'de> for GlobVisitor {
type Value = Glob;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("glob")
}
// Deserialize ["included","globs","only"]
fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
Ok(Glob {
// At time of writing the default value of allow_empty is true.
// We may want to change this if the default changes in Bazel.
allow_empty: true,
include: BTreeSet::deserialize(SeqAccessDeserializer::new(seq))?,
exclude: BTreeSet::new(),
})
}
// Deserialize {"include":["included","globs"],"exclude":["excluded","globs"]}
fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
fn default_true() -> bool {
true
}
#[derive(serde::Deserialize)]
struct GlobMap {
#[serde(default = "default_true")]
allow_empty: bool,
include: BTreeSet<String>,
#[serde(default)]
exclude: BTreeSet<String>,
}
let glob_map = GlobMap::deserialize(MapAccessDeserializer::new(map))?;
Ok(Glob {
allow_empty: glob_map.allow_empty,
include: glob_map.include,
exclude: glob_map.exclude,
})
}
}