Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic dictionary impl #92

Merged
merged 4 commits into from Jan 28, 2023
Merged

Conversation

lilizoey
Copy link
Member

@lilizoey lilizoey commented Jan 27, 2023

Add basic dictionary impl with:

  • From for HashMap and HashSet (with true as the values)
  • FromIterator for (K,V)
  • methods from godot, or a rusty substitute
  • dict! macro to easily make dictionaries godot-style

missing:

  • iteration
  • get_mut (and other _mut functions)
  • Entry-api (if possible)
  • key = value syntax for dict! macro

The added PartialEq => array_operator_equal impl in Array is there to simplify a test, but can be removed. But i think it's gonna be added eventually anyway.

I'm also not entirely sure about the safety of using dictionaries, my guess is that it's the same as for array though.

godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
Copy link
Member

@Bromeon Bromeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot, this is very valuable work to get initial Dictionary support! 🙂

Added some comments. As a small nitpick, could you end documentation lines with a full stop, even if they are short? E.g:

/// Constructs an empty `Dictionary`
pub fn new() -> Self {...}

becomes

/// Constructs an empty `Dictionary`.
pub fn new() -> Self {...}

godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/string.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
@Bromeon
Copy link
Member

Bromeon commented Jan 28, 2023

bors try

bors bot added a commit that referenced this pull request Jan 28, 2023
@bors
Copy link
Contributor

bors bot commented Jan 28, 2023

try

Build failed:

@ttencate
Copy link
Contributor

The added Eq => array_operator_equal impl in Array is there to simplify a test, but can be removed. But i think it's gonna be added eventually anyway.

PartialEq will be! And PartialOrd too. Holding off on Eq and Ord because of Godot's inconsistent handling of NaNs that you discovered.

@chitoyuu
Copy link

Floats aren't Eq in Rust so it naturally follows that collections that may contain floats shouldn't be Eq either. If the full trait is desirable we can maybe add a marker trait for element types that satisfy Eq when converted to their Godot representations, similar to how ToVariantEq works in gdnative.

Copy link
Member

@Bromeon Bromeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update!

Instead of impl ToVariant, can you use explicit generic arguments? That allows the caller to specify them, to dis-ambiguate the call if needed.

So instead of

pub fn get(&self, key: impl ToVariant) -> Option<Variant>

you'd have

pub fn get<K: ToVariant>(&self, key: K) -> Option<Variant>

godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
Comment on lines 318 to 336
/// Creates a new dictionary with the given keys and values, the syntax mirrors
/// godot's dictionary creation syntax.
///
/// Any value can be used as a key, but to use an expression you need to surround it
/// in `()` or `{}`
///
/// Example
/// ```rust, no_run
/// # #[macro_use] extern crate godot_core;
/// # fn main() {
/// let key = "my_key";
/// let d = dict! {
/// "key1": 10,
/// "another": Variant::nil(),
/// key: true,
/// (1 + 2): "final",
/// }
/// # }
/// ```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicks:

  • uppercase "Godot"
  • missing colon after "Example"
  • missing full stops at end of sentences
  • ```rust, no_run -> ```no_run (Rust is implied)

Maybe check this in other places as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i uppercased "Godot" in all the documentation i could find. i found two places i forgot a full stop too, hopefully i didnt miss anything else.

godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
@Bromeon
Copy link
Member

Bromeon commented Jan 28, 2023

bors try

bors bot added a commit that referenced this pull request Jan 28, 2023
@bors
Copy link
Contributor

bors bot commented Jan 28, 2023

try

Build failed:

bors bot added a commit that referenced this pull request Jan 28, 2023
Copy link
Member

@Bromeon Bromeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot, it looks very good by now! Few things remaining, then we should be good to go 🚀

Also, CI failed due to a network error, I'll restart it.
bors try

godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
Comment on lines +247 to +261
/// Convert the keys of this dictionary to a strongly typed rust `HashSet`. If the
/// conversion fails for any key, an error is returned.
impl<K: FromVariant + Eq + std::hash::Hash> TryFrom<&Dictionary> for HashSet<K> {
type Error = VariantConversionError;

fn try_from(dictionary: &Dictionary) -> Result<Self, Self::Error> {
// TODO: try to panic or something if modified while iterating
// Though probably better to fix when implementing iteration proper
dictionary
.keys()
.iter_shared()
.map(|key| K::try_from_variant(&key))
.collect()
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is OK for now, but might later be removed, once we have full iterator support.

Reason: maps and sets are different data structures, so I'm not sure if a direct From/TryFrom conversion is the right approach. For example, there is no such conversion between HashMap and HashSet in the standard library.

Instead, we can add iterators over key-value pairs, keys and values. It should then be relatively simple to collect() them into their respective data structures, and we can make this API more versatile and agnostic of concrete types like HashSet.

itest/rust/src/variant_test.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/dictionary.rs Outdated Show resolved Hide resolved
bors bot added a commit that referenced this pull request Jan 28, 2023
@godot-rust godot-rust deleted a comment from bors bot Jan 28, 2023
@bors
Copy link
Contributor

bors bot commented Jan 28, 2023

try

Build failed:

Hopefully the `from_sys_init` thing used in array will stop the `duplicate` crash
Copy link
Member

@Bromeon Bromeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again for this great PR and the extensive testing! 👍

bors r+

@Bromeon Bromeon added feature Adds functionality to the library c: core Core components labels Jan 28, 2023
@bors
Copy link
Contributor

bors bot commented Jan 28, 2023

Build succeeded:

@bors bors bot merged commit 6ae8ffd into godot-rust:master Jan 28, 2023
@Bromeon
Copy link
Member

Bromeon commented Jan 28, 2023

Manually re-merged in 188aa69, as I forgot to squash 🙃

This was referenced Feb 3, 2023
@lilizoey lilizoey deleted the feature/dictionary branch April 16, 2023 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: core Core components feature Adds functionality to the library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants