Skip to content

Simplify data structure #266

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

Open
wants to merge 41 commits into
base: dev
Choose a base branch
from

Conversation

Arkatufus
Copy link
Contributor

Remove implicit casting

# Conflicts:
#	src/Hocon.API.Tests/HoconAPISpec.ApproveConfiguration.approved.txt
#	src/Hocon.Configuration/Config.cs
#	src/Hocon.Configuration/HoconConfigurationFactory.cs
# Conflicts:
#	src/Hocon.API.Tests/HoconAPISpec.ApproveCore.approved.txt
#	src/Hocon/HoconObject.cs
Copy link
Member

@Aaronontheweb Aaronontheweb left a comment

Choose a reason for hiding this comment

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

Some changes, some questions

@@ -45,7 +45,6 @@
<ItemGroup>
<ProjectReference Include="..\Hocon.Configuration\Hocon.Configuration.csproj" />
<ProjectReference Include="..\Hocon.Extensions.Configuration\Hocon.Extensions.Configuration.csproj" />
<ProjectReference Include="..\Hocon.Immutable\Hocon.Immutable.csproj" />
Copy link
Member

Choose a reason for hiding this comment

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

Yep, good to see Hocon.Immutable getting disposed

public static Hocon.Config Empty { get; }
public virtual System.Collections.Generic.IReadOnlyList<Hocon.HoconValue> Fallbacks { get; }
public virtual System.Collections.Generic.IReadOnlyList<Hocon.HoconObject> Fallbacks { get; }
Copy link
Member

Choose a reason for hiding this comment

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

What's the significance of this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's no such thing as HoconValue anymore, the structure is simplified.

public string ToString(bool useFallbackValues) { }
protected override bool TryGetNode(Hocon.HoconPath path, out Hocon.HoconValue result) { }
public override bool TryGetValue(Hocon.HoconPath path, out Hocon.HoconElement result) { }
Copy link
Member

Choose a reason for hiding this comment

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

Same as above - what's the significance of this change too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same as the above, there is no HoconValue class.

}
public sealed class HoconBool : Hocon.HoconLiteral
public sealed class HoconArrayBuilder : System.Collections.Generic.List<Hocon.HoconElement>
Copy link
Member

Choose a reason for hiding this comment

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

Like the idea of using the builder pattern to build up the HOCON, but we need to avoid inheriting directly from mutable base classes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is no danger, the builder pattern is only used for building the hocon classes, all the returned built classes are immutable.

@@ -31,19 +31,6 @@ public class MyObjectConfig
public int[] IntergerArray { get; set; }
}

[Fact]
public void Config_should_be_serializable()
Copy link
Member

Choose a reason for hiding this comment

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

Fine deferring this for now

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is moved to SerializationSpec. Config does not support direct JSON serialization anymore, because of immutability.


namespace Hocon
{
public sealed class HoconObjectBuilder : SortedDictionary<string, HoconElement>
Copy link
Member

Choose a reason for hiding this comment

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

Same as above - might want to make internal


public new HoconElement this[string path] {
get => GetValue(path);
set => throw new InvalidOperationException("HoconObject is a read only Dictionary.");
Copy link
Member

Choose a reason for hiding this comment

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

Can we avoid this by just not inheriting from IDictionary - leave it as IReadOnlyDictionary only? Or did you need this for testing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IDictionary interface is needed for backward compatibility, I've blocked all of the write behaviour

if(root is Config cfg)
{
Root = cfg.Root;
_fallbacks = cfg._fallbacks.ToList();
Copy link
Member

Choose a reason for hiding this comment

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

Why is the ToList() call necessary here? Can the cfg._fallbacks property be modified?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, each Config instance need to have their own separate instance of fallbacks, else changing (appending a new fallback value in WithFallback) will affect ALL Config objects before it.

protected List<HoconValue> _fallbacks { get; } = new List<HoconValue>();
public virtual IReadOnlyList<HoconValue> Fallbacks => _fallbacks.ToList().AsReadOnly();
protected List<HoconObject> _fallbacks { get; } = new List<HoconObject>();
public virtual IReadOnlyList<HoconObject> Fallbacks => _fallbacks.ToList().AsReadOnly();
Copy link
Member

Choose a reason for hiding this comment

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

No need to call ToList().AsReadOnly() - List<T> is castable to IReadOnlyList<T>

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Defensive coding, I want to be 100% sure that the user could not change the internal representation of the fallback list.


if (fallback.IsNullOrEmpty())
return this; // no-op

if (IsEmpty)
return fallback;

return new Config(this, fallback);
var result = new Config(this);
result.MergeConfig(fallback);
Copy link
Member

Choose a reason for hiding this comment

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

So this just appends the latest fallback to what position on the linked list?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fallbacks are always added to the back of the chain

@Aaronontheweb
Copy link
Member

Going to do a perf comparison in a second - stay tuned

@Aaronontheweb
Copy link
Member

Sigh, all of my performance comparison posts got added to here by accident: akkadotnet/akka.net#4301 (comment)

Performance in this PR is looking good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants