1use yog_ids::sep::{
4 PROPERTY_IS, PROPERTY_SEP, STATE_CLOSE as PROPS_CLOSE, STATE_OPEN as PROPS_OPEN,
5};
6
7pub fn split_state(state: &str) -> (&str, Vec<(&str, &str)>) {
9 let (id, rest) = state.split_once(PROPS_OPEN).unwrap_or((state, ""));
10 let props = rest
11 .trim_end_matches(PROPS_CLOSE)
12 .split(PROPERTY_SEP)
13 .filter_map(|p| p.split_once(PROPERTY_IS))
14 .collect();
15 (id, props)
16}
17
18pub fn join_state(id: &str, props: &[(&str, &str)]) -> String {
20 if props.is_empty() {
21 return id.to_owned();
22 }
23 let props: Vec<String> = props
24 .iter()
25 .map(|(k, v)| format!("{k}{PROPERTY_IS}{v}"))
26 .collect();
27 format!("{id}{PROPS_OPEN}{}{PROPS_CLOSE}", props.join(PROPERTY_SEP))
28}
29
30#[cfg(test)]
31mod tests {
32 use super::split_state;
33
34 #[test]
35 fn a_state_joins_back() {
36 assert_eq!(super::join_state("minecraft:stone", &[]), "minecraft:stone");
37 assert_eq!(
38 super::join_state("a:b", &[("x", "1"), ("y", "2")]),
39 "a:b[x=1,y=2]"
40 );
41 }
42
43 #[test]
44 fn a_state_splits_into_its_id_and_properties() {
45 assert_eq!(split_state("minecraft:stone"), ("minecraft:stone", vec![]));
46 assert_eq!(
47 split_state("hexcasting:impetus/look[energized=false,facing=up]"),
48 (
49 "hexcasting:impetus/look",
50 vec![("energized", "false"), ("facing", "up")]
51 )
52 );
53 }
54}