Skip to content

Commit

Permalink
✨ Partially implement info subcommand
Browse files Browse the repository at this point in the history
  • Loading branch information
VixieTSQ committed Oct 13, 2022
1 parent fa456a4 commit 892d825
Show file tree
Hide file tree
Showing 18 changed files with 314 additions and 268 deletions.
72 changes: 72 additions & 0 deletions rustfmt.toml
@@ -0,0 +1,72 @@
max_width = 160
hard_tabs = false
tab_spaces = 4
newline_style = "Unix"
indent_style = "Block"
use_small_heuristics = "Off"
chain_width = 85
wrap_comments = true
format_code_in_doc_comments = false
comment_width = 80
normalize_comments = true
normalize_doc_attributes = true
format_strings = true
format_macro_matchers = true
format_macro_bodies = true
hex_literal_case = "Preserve"
empty_item_single_line = true
struct_lit_single_line = true
struct_lit_width = 18
fn_single_line = true
where_single_line = false
imports_indent = "Block"
imports_layout = "Mixed"
imports_granularity = "Module"
group_imports = "StdExternalCrate"
reorder_imports = true
reorder_modules = true
reorder_impl_items = true
type_punctuation_density = "Wide"
space_before_colon = false
space_after_colon = true
spaces_around_ranges = false
binop_separator = "Front"
remove_nested_parens = true
combine_control_expr = true
short_array_element_width_threshold = 16
overflow_delimited_expr = true
struct_field_align_threshold = 0
enum_discrim_align_threshold = 0
match_arm_blocks = true
match_arm_leading_pipes = "Never"
force_multiline_blocks = false
fn_args_layout = "Tall"
brace_style = "SameLineWhere"
control_brace_style = "AlwaysSameLine"
trailing_semicolon = true
trailing_comma = "Vertical"
match_block_trailing_comma = true
blank_lines_upper_bound = 1
blank_lines_lower_bound = 0
edition = "2021"
version = "One"
inline_attribute_width = 0
format_generated_files = false
merge_derives = true
use_try_shorthand = true
use_field_init_shorthand = true
force_explicit_abi = true
condense_wildcard_suffixes = false
color = "Auto"
required_version = "1.5.1"
unstable_features = false
disable_all_formatting = false
skip_children = false
hide_parse_errors = false
error_on_line_overflow = false
error_on_unformatted = false
ignore = [
"crates/block_parser"
]
emit_mode = "Files"
make_backup = false
60 changes: 27 additions & 33 deletions src/blocks/intermediary/collisions.rs
@@ -1,10 +1,9 @@
use ahash::{AHashMap, AHashSet};
use serde::de::{DeserializeSeed, IgnoredAny, Visitor};
use serde::Deserialize;
use serde::de::{Visitor, IgnoredAny, DeserializeSeed};

use crate::blocks::raw::property::{EnumProperty, PropertyKind};

use super::rules::ModernPropertyRules;
use crate::blocks::raw::property::{EnumProperty, PropertyKind};

/// A collection of possible property collisions in raw data.
///
Expand All @@ -27,9 +26,7 @@ pub struct CollisionList<'raw> {
}

impl<'raw> CollisionList<'raw> {
pub fn should_exit(&self) -> bool {
!self.by_name.is_empty()
}
pub fn should_exit(&self) -> bool { !self.by_name.is_empty() }

/// Displays a summary of the different collisions found in the raw data.
pub fn display(&self) {
Expand Down Expand Up @@ -62,41 +59,42 @@ pub struct CollisionRuleProvider<'a, 'raw>(Option<&'a ModernPropertyRules<'raw>>

impl<'a, 'raw> CollisionRuleProvider<'a, 'raw> {
/// Constructs a new `CollisionRuleProvider` given a set of rules
pub fn new(rules: Option<&'a ModernPropertyRules<'raw>>) -> Self {
Self(rules)
}
pub fn new(rules: Option<&'a ModernPropertyRules<'raw>>) -> Self { Self(rules) }

/// This transformation does two checks:
/// - First it makes sure the property name is not `"type"`, this will get transformed into `"kind"`
/// - Secondly it uses the rules, if present, to replace the property name if there's a match based on the property values
/// - First it makes sure the property name is not `"type"`, this will get
/// transformed into `"kind"`
/// - Secondly it uses the rules, if present, to replace the property name
/// if there's a match based on the property values
pub fn transform<'b, I>(&'b self, properties: I) -> impl Iterator<Item = (&'raw str, PropertyKind<'raw>)> + 'b
where
I: IntoIterator<Item = (&'raw str, PropertyKind<'raw>)> + 'b,
{
properties.into_iter()
.map(|(name, property)| {
let name = if name == "type" { "kind" } else { name };
if let Some(rules) = self.0 {
rules.transform(name, property)
} else {
(name, property)
}
})
properties.into_iter().map(|(name, property)| {
let name = if name == "type" {
"kind"
} else {
name
};
if let Some(rules) = self.0 {
rules.transform(name, property)
} else {
(name, property)
}
})
}
}

impl<'a, 'raw, 'de: 'raw> Visitor<'de> for CollisionRuleProvider<'a, 'raw> {
type Value = CollisionList<'raw>;

fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a 1.13+ minecraft-generated block list")
}
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { formatter.write_str("a 1.13+ minecraft-generated block list") }

/// Simply collect all the properties and keep the ones
/// that share either name or values
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
where
A: serde::de::MapAccess<'de>,
{
let mut by_name = AHashMap::<&'raw str, AHashSet<EnumProperty>>::new();
let mut by_values = AHashMap::<EnumProperty<'raw>, AHashSet<&'raw str>>::new();
Expand All @@ -115,19 +113,16 @@ impl<'a, 'raw, 'de: 'raw> Visitor<'de> for CollisionRuleProvider<'a, 'raw> {
} else {
by_name.insert(name, AHashSet::from([property]));
}
}
_ => {}
},
_ => {},
}
}
}

by_name.retain(|_, set| set.len() > 1);
by_values.retain(|_, set| set.len() > 1);

Ok(CollisionList {
by_name,
by_values,
})
Ok(CollisionList { by_name, by_values })
}
}

Expand All @@ -136,7 +131,7 @@ impl<'a, 'raw, 'de: 'raw> DeserializeSeed<'de> for CollisionRuleProvider<'a, 'ra

fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>
D: serde::Deserializer<'de>,
{
deserializer.deserialize_map(self)
}
Expand All @@ -149,4 +144,3 @@ struct RawBlockData<'raw> {
#[serde(rename = "states")]
_states: IgnoredAny,
}

60 changes: 32 additions & 28 deletions src/blocks/intermediary/data.rs
@@ -1,6 +1,8 @@
use ahash::RandomState;
use hashlink::LinkedHashMap;
use serde::{Deserialize, Serialize};

use super::MetaData;
use crate::blocks::raw::property::EnumProperty;
use crate::util::identifier::Identifier;

Expand All @@ -14,23 +16,27 @@ pub type BlockList<'raw> = LinkedHashMap<Identifier<'raw>, ModernBlockData<'raw>
/// The compact blockstates format.
///
/// In this format there are two lists:
/// - The first list is a list of all possible properties.
/// i.e. a property name mapped to more than one property value.
/// - The second list is a list of all the blocks.
/// i.e. a collection of blockstates, if the block has one or more properties
/// it will have these listed referring to the first list when it's an enum property.
/// If the block has more than one blockstate, there will also be a `default_id` field.
/// - The first list is a list of all possible properties. i.e. a property name
/// mapped to more than one property value.
/// - The second list is a list of all the blocks. i.e. a collection of
/// blockstates, if the block has one or more properties it will have these
/// listed referring to the first list when it's an enum property. If the
/// block has more than one blockstate, there will also be a `default_id`
/// field.
#[derive(Debug, Serialize, Deserialize)]
pub struct ModernBlockList<'raw> {
#[serde(borrow)]
properties: PropertyList<'raw>,
pub metadata: Option<MetaData<'raw>>,
#[serde(borrow)]
pub properties: PropertyList<'raw>,
#[serde(borrow)]
blocks: BlockList<'raw>,
pub blocks: BlockList<'raw>,
}

impl<'raw> ModernBlockList<'raw> {
pub(crate) fn new(properties: PropertyList<'raw>, blocks: BlockList<'raw>) -> Self {
pub(crate) fn new(metadata: Option<MetaData<'raw>>, properties: PropertyList<'raw>, blocks: BlockList<'raw>) -> Self {
ModernBlockList {
metadata,
properties,
blocks,
}
Expand All @@ -39,25 +45,29 @@ impl<'raw> ModernBlockList<'raw> {

/// Compact way of identifying block data.
///
/// Only if the block has one ore more properties, the [`ModernBlockData::kinds`]
/// will be serialized. If the block has more than one blockstate,
/// a default_id field will be serialized as well.
/// Only if the block has one ore more properties, the
/// [`ModernBlockData::kinds`] will be serialized. If the block has more than
/// one blockstate, a default_id field will be serialized as well.
#[derive(Debug, Serialize, Deserialize)]
pub struct ModernBlockData<'raw> {
#[serde(borrow, skip_serializing_if = "LinkedHashMap::is_empty", rename = "properties")]
kinds: LinkedHashMap<&'raw str, PropertyValue<'raw>, RandomState>,
#[serde(borrow, skip_serializing_if = "Option::is_none", rename = "properties")]
kinds: Option<LinkedHashMap<&'raw str, PropertyValue<'raw>, RandomState>>,
#[serde(rename = "base")]
base_id: i32,
pub base_id: i32,
#[serde(skip_serializing_if = "Option::is_none", rename = "default")]
default_id: Option<i32>,
pub default_id: Option<i32>,
}

impl<'raw> ModernBlockData<'raw> {
pub fn new(kinds: LinkedHashMap<&'raw str, PropertyValue<'raw>, RandomState>, base_id: i32, default_id: Option<i32>) -> Self {
ModernBlockData {
kinds,
kinds: if kinds.is_empty() {
None
} else {
Some(kinds)
},
base_id,
default_id
default_id,
}
}
}
Expand All @@ -72,15 +82,9 @@ pub enum PropertyValue<'raw> {
}

impl<'raw> PropertyValue<'raw> {
pub fn bool() -> Self {
Self::Bool("bool")
}
pub fn bool() -> Self { Self::Bool("bool") }

pub fn enum_name(value: &'raw str) -> Self {
Self::Enum(value)
}

pub fn range(start: u8, end: u8) -> Self {
Self::Range([start, end])
}
pub fn enum_name(value: &'raw str) -> Self { Self::Enum(value) }

pub fn range(start: u8, end: u8) -> Self { Self::Range([start, end]) }
}
30 changes: 4 additions & 26 deletions src/blocks/intermediary/metadata.rs
@@ -1,36 +1,14 @@
use std::borrow::Cow;

use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize)]
pub struct MetaData<'raw> {
id: i32,
pub id: i32,
#[serde(skip_serializing_if = "Option::is_none")]
name: Option<&'raw str>,
pub name: Option<&'raw str>,
#[serde(skip_serializing_if = "Option::is_none")]
note: Option<&'raw str>,
pub note: Option<&'raw str>,
}

impl<'raw> MetaData<'raw> {
pub fn new(id: i32, name: Option<&'raw str>, note: Option<&'raw str>) -> Self {
Self {
id,
name,
note,
}
}

pub fn id(&self) -> i32 {
self.id
}

pub fn name(&self) -> Cow<'raw, str> {
self.name
.map(|name| name.into())
.unwrap_or(Cow::Owned(self.id.to_string()))
}

pub fn note(&self) -> Option<&'raw str> {
self.note
}
pub fn new(id: i32, name: Option<&'raw str>, note: Option<&'raw str>) -> Self { Self { id, name, note } }
}
1 change: 0 additions & 1 deletion src/blocks/intermediary/mod.rs
Expand Up @@ -4,4 +4,3 @@ mod metadata;
pub mod rules;

pub use metadata::MetaData;

11 changes: 4 additions & 7 deletions src/blocks/intermediary/rules.rs
@@ -1,10 +1,10 @@
use ahash::RandomState;
use hashlink::LinkedHashMap;
use serde::Deserialize;
use serde::{Deserialize, Serialize};

use crate::blocks::raw::property::{EnumProperty, PropertyKind};

#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, Serialize)]
#[serde(from = "LinkedHashMap<&'raw str, EnumProperty<'raw>, RandomState>")]
pub struct ModernPropertyRules<'raw> {
#[serde(borrow, flatten)]
Expand All @@ -15,18 +15,15 @@ impl<'raw> ModernPropertyRules<'raw> {
pub fn transform(&self, name: &'raw str, property: PropertyKind<'raw>) -> (&'raw str, PropertyKind<'raw>) {
match &property {
PropertyKind::Enum(enum_property) => (self.rule_data.get(&enum_property).cloned().unwrap_or(name), property),
_ => (name, property)
_ => (name, property),
}
}
}

impl<'raw> From<LinkedHashMap<&'raw str, EnumProperty<'raw>, RandomState>> for ModernPropertyRules<'raw> {
fn from(other: LinkedHashMap<&'raw str, EnumProperty<'raw>, RandomState>) -> Self {
Self {
rule_data: other.into_iter()
.map(|(name, values)| (values, name))
.collect(),
rule_data: other.into_iter().map(|(name, values)| (values, name)).collect(),
}
}
}

0 comments on commit 892d825

Please sign in to comment.