Skip to content

Commit

Permalink
feat(config): struct pointers
Browse files Browse the repository at this point in the history
  • Loading branch information
yair-starkware committed Nov 12, 2024
1 parent fcb2b8e commit 4c80d65
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 4 deletions.
93 changes: 92 additions & 1 deletion crates/papyrus_config/src/config_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use validator::Validate;
use crate::command::{get_command_matches, update_config_map_by_command_args};
use crate::converters::deserialize_milliseconds_to_duration;
use crate::dumping::{
append_struct_pointer,
append_sub_config_name,
combine_config_map_and_pointers,
required_param_description,
Expand All @@ -27,6 +28,8 @@ use crate::dumping::{
ser_pointer_target_param,
ser_pointer_target_required_param,
ser_required_param,
set_pointing_param_paths,
ConfigPointers,
SerializeConfig,
};
use crate::loading::{
Expand Down Expand Up @@ -469,6 +472,94 @@ fn test_replace_pointers() {
assert_matches!(err, ConfigError::PointerTargetNotFound { .. });
}

#[test]
fn test_struct_pointers() {
const TARGET_PREFIX: &str = "base";
let target_value =
RequiredConfig { param_path: "Not a default param_path.".to_owned(), num: 10 };
let config_map = StructPointersConfig::default().dump();

let mut pointers = ConfigPointers::new();
append_struct_pointer(
&mut pointers,
TARGET_PREFIX.to_owned(),
&target_value,
set_pointing_param_paths(&["a", "b"]),
);
let stored_map =
combine_config_map_and_pointers(config_map, &pointers, &HashSet::default()).unwrap();

// Assert the pointing parameters are correctly set.
assert_eq!(
stored_map["a.param_path"],
json!(SerializedParam {
description: required_param_description("This is param_path.").to_owned(),
content: SerializedContent::PointerTarget(
format!("{TARGET_PREFIX}.param_path").to_owned()
),
privacy: ParamPrivacy::Public,
})
);
assert_eq!(
stored_map["a.num"],
json!(SerializedParam {
description: "This is num.".to_owned(),
content: SerializedContent::PointerTarget(format!("{TARGET_PREFIX}.num").to_owned()),
privacy: ParamPrivacy::Public,
})
);
assert_eq!(
stored_map["b.param_path"],
json!(SerializedParam {
description: required_param_description("This is param_path.").to_owned(),
content: SerializedContent::PointerTarget(
format!("{TARGET_PREFIX}.param_path").to_owned()
),
privacy: ParamPrivacy::Public,
})
);
assert_eq!(
stored_map["b.num"],
json!(SerializedParam {
description: "This is num.".to_owned(),
content: SerializedContent::PointerTarget(format!("{TARGET_PREFIX}.num").to_owned()),
privacy: ParamPrivacy::Public,
})
);

// Assert the pointed parameter is correctly set.
assert_eq!(
stored_map[format!("{TARGET_PREFIX}.param_path").to_owned()],
json!(SerializedParam {
description: required_param_description("This is param_path.").to_owned(),
content: SerializedContent::ParamType(SerializationType::String),
privacy: ParamPrivacy::TemporaryValue,
})
);
assert_eq!(
stored_map[format!("{TARGET_PREFIX}.num").to_owned()],
json!(SerializedParam {
description: "This is num.".to_owned(),
content: SerializedContent::DefaultValue(json!(10)),
privacy: ParamPrivacy::TemporaryValue,
})
);
}

#[derive(Clone, Default, Serialize, Deserialize, Debug, PartialEq)]
struct StructPointersConfig {
pub a: RequiredConfig,
pub b: RequiredConfig,
}
impl SerializeConfig for StructPointersConfig {
fn dump(&self) -> BTreeMap<ParamPath, SerializedParam> {
let mut dump = BTreeMap::new();
dump.append(&mut append_sub_config_name(self.a.dump(), "a"));
dump.append(&mut append_sub_config_name(self.b.dump(), "b"));
dump
}
}

#[derive(Clone, Default, Serialize, Deserialize, Debug, PartialEq)]
struct CustomConfig {
param_path: String,
Expand Down Expand Up @@ -565,7 +656,7 @@ fn serialization_precision() {
assert_eq!(input, deserialized);
}

#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
#[derive(Clone, Default, Serialize, Deserialize, Debug, PartialEq)]
struct RequiredConfig {
param_path: String,
num: usize,
Expand Down
41 changes: 40 additions & 1 deletion crates/papyrus_config/src/dumping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,44 @@ pub type Pointers = HashSet<ParamPath>;
/// Detailing pointers in the config map.
pub type ConfigPointers = Vec<(PointerTarget, Pointers)>;

/// Given set of paths that are configuration of the same struct type, makes all the paths point to
/// the same target.
pub fn append_struct_pointer<T: SerializeConfig>(
config_pointers: &mut ConfigPointers,
target_prefix: ParamPath,
default_instance: &T,
pointer_prefixes: HashSet<ParamPath>,
) {
let target_dump = default_instance.dump();
for (param_path, serialized_param) in target_dump {
let full_param_path = format!("{}{}{}", target_prefix, FIELD_SEPARATOR, param_path);
let pointer_target = match &serialized_param.content {
SerializedContent::DefaultValue(value) => {
ser_pointer_target_param(&full_param_path, value, &serialized_param.description)
}
SerializedContent::ParamType(serialization_type) => {
let description = serialized_param
.description
.strip_prefix(REQUIRED_PARAM_DESCRIPTION_PREFIX)
.unwrap_or(&serialized_param.description);
ser_pointer_target_required_param(
&full_param_path,
*serialization_type,
description,
)
}
SerializedContent::PointerTarget(_) => panic!("Pointer target cannot be a pointer."),
};
config_pointers.push((
pointer_target,
pointer_prefixes
.iter()
.map(|pointer| format!("{}{}{}", pointer, FIELD_SEPARATOR, param_path))
.collect(),
));
}
}

/// Serialization for configs.
pub trait SerializeConfig {
/// Conversion of a configuration to a mapping of flattened parameters to their descriptions and
Expand Down Expand Up @@ -349,8 +387,9 @@ pub fn set_pointing_param_paths(param_path_list: &[&str]) -> Pointers {
param_paths
}

const REQUIRED_PARAM_DESCRIPTION_PREFIX: &str = "A required param! ";
pub(crate) fn required_param_description(description: &str) -> String {
format!("A required param! {}", description)
format!("{REQUIRED_PARAM_DESCRIPTION_PREFIX}{}", description)
}

/// Verifies that params whose name matches a pointer target either point at it, or are whitelisted.
Expand Down
4 changes: 2 additions & 2 deletions crates/papyrus_config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ impl SerializedContent {
_ => None,
},
SerializedContent::PointerTarget(_) => None,
SerializedContent::ParamType(ser_type) => Some(ser_type.clone()),
SerializedContent::ParamType(ser_type) => Some(*ser_type),
}
}
}
Expand All @@ -149,7 +149,7 @@ pub struct SerializedParam {
}

/// A serialized type of a configuration parameter.
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, strum_macros::Display)]
#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, strum_macros::Display)]
#[allow(missing_docs)]
pub enum SerializationType {
Boolean,
Expand Down

0 comments on commit 4c80d65

Please sign in to comment.