Skip to content

Commit

Permalink
Isolate the key marshallign functionlity publicly for improved intent
Browse files Browse the repository at this point in the history
  • Loading branch information
inputfalken committed Oct 1, 2023
1 parent bbc9ab6 commit 4751bdb
Show file tree
Hide file tree
Showing 13 changed files with 95 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,31 @@ public partial class DynamoDBGsiKeyMarshallerTests
[Fact]
public void PartitionKey_MissMatchedIndexName_ShouldThrow()
{
var act = () => GsiHashAndRangeKeyMarshallerWithIndex("Unknown").PartitionKey("test");
var act = () => GsiHashAndRangeKeyMarshaller.IndexKeyMarshaller("Unknown").PartitionKey("test");

act.Should().Throw<ArgumentOutOfRangeException>();
}

[Fact]
public void RangeKey_MissMatchedIndexName_ShouldThrow()
{
var act = () => GsiHashAndRangeKeyMarshallerWithIndex("Unknown").RangeKey("test");
var act = () => GsiHashAndRangeKeyMarshaller.IndexKeyMarshaller("Unknown").RangeKey("test");

act.Should().Throw<ArgumentOutOfRangeException>();
}

[Fact]
public void Keys_MissMatchedIndexName_ShouldThrow()
{
var act = () => GsiHashAndRangeKeyMarshallerWithIndex("Unknown").Keys("1", 1);
var act = () => GsiHashAndRangeKeyMarshaller.IndexKeyMarshaller("Unknown").Keys("1", 1);

act.Should().Throw<ArgumentOutOfRangeException>();
}

[Fact]
public void PartitionKey_MatchedIndexName_ShouldMapCorrectly()
{
GsiHashAndRangeKeyMarshallerWithIndex(GsiHashAndRangeKey.IndexName)
GsiHashAndRangeKeyMarshaller.IndexKeyMarshaller(GsiHashAndRangeKey.IndexName)
.PartitionKey("[email protected]")
.Should()
.SatisfyRespectively(x =>
Expand All @@ -44,7 +44,7 @@ public void PartitionKey_MatchedIndexName_ShouldMapCorrectly()
[Fact]
public void RangeKey_MatchedIndexName_ShouldMapCorrectly()
{
GsiHashAndRangeKeyMarshallerWithIndex(GsiHashAndRangeKey.IndexName)
GsiHashAndRangeKeyMarshaller.IndexKeyMarshaller(GsiHashAndRangeKey.IndexName)
.RangeKey(1)
.Should()
.SatisfyRespectively(x =>
Expand All @@ -57,7 +57,7 @@ public void RangeKey_MatchedIndexName_ShouldMapCorrectly()
[Fact]
public void Keys_MatchedIndexName_ShouldMapCorrectly()
{
GsiHashAndRangeKeyMarshallerWithIndex(GsiHashAndRangeKey.IndexName)
GsiHashAndRangeKeyMarshaller.IndexKeyMarshaller(GsiHashAndRangeKey.IndexName)
.Keys("[email protected]", 1)
.Should()
.SatisfyRespectively(x =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,31 @@ public partial class DynamoDBLsiKeyMarshallerTests
[Fact]
public void PartitionKey_MissMatchedIndexName_ShouldThrow()
{
var act = () => LsiHashAndRangeKeyMarshallerWithIndex("Unknown").PartitionKey("test");
var act = () => LsiHashAndRangeKeyMarshaller.IndexKeyMarshaller("Unknown").PartitionKey("test");

act.Should().Throw<ArgumentOutOfRangeException>();
}

[Fact]
public void RangeKey_MissMatchedIndexName_ShouldThrow()
{
var act = () => LsiHashAndRangeKeyMarshallerWithIndex("Unknown").RangeKey("test");
var act = () => LsiHashAndRangeKeyMarshaller.IndexKeyMarshaller("Unknown").RangeKey("test");

act.Should().Throw<ArgumentOutOfRangeException>();
}

[Fact]
public void Keys_MissMatchedIndexName_ShouldThrow()
{
var act = () => LsiHashAndRangeKeyMarshallerWithIndex("Unknown").Keys("1", 1);
var act = () => LsiHashAndRangeKeyMarshaller.IndexKeyMarshaller("Unknown").Keys("1", 1);

act.Should().Throw<ArgumentOutOfRangeException>();
}

[Fact]
public void PartitionKey_MatchedIndexName_ShouldMapCorrectly()
{
LsiHashAndRangeKeyMarshallerWithIndex(LsiHashAndRangeKey.IndexName)
LsiHashAndRangeKeyMarshaller.IndexKeyMarshaller(LsiHashAndRangeKey.IndexName)
.PartitionKey("[email protected]")
.Should()
.SatisfyRespectively(x =>
Expand All @@ -44,7 +44,7 @@ public void PartitionKey_MatchedIndexName_ShouldMapCorrectly()
[Fact]
public void RangeKey_MatchedIndexName_ShouldMapCorrectly()
{
LsiHashAndRangeKeyMarshallerWithIndex(LsiHashAndRangeKey.IndexName)
LsiHashAndRangeKeyMarshaller.IndexKeyMarshaller(LsiHashAndRangeKey.IndexName)
.RangeKey(1)
.Should()
.SatisfyRespectively(x =>
Expand All @@ -57,7 +57,7 @@ public void RangeKey_MatchedIndexName_ShouldMapCorrectly()
[Fact]
public void Keys_MatchedIndexName_ShouldMapCorrectly()
{
LsiHashAndRangeKeyMarshallerWithIndex(LsiHashAndRangeKey.IndexName)
LsiHashAndRangeKeyMarshaller.IndexKeyMarshaller(LsiHashAndRangeKey.IndexName)
.Keys("[email protected]", 1)
.Should()
.SatisfyRespectively(x =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public partial class DynamoDBPrimaryKeyMarshallerTests
public void PartitionKey_TypeWithPartitionKeyOnly_ShouldSucceed()
{
var type = _fixture.Create<TypeWithPartitionKeyOnly>();
PartitionKeyOnly
PartitionKeyOnly.PrimaryKeyMarshaller
.PartitionKey(type.Id)
.Should()
.SatisfyRespectively(x =>
Expand All @@ -30,7 +30,7 @@ public void PartitionKey_TypeWithPartitionKeyOnly_ShouldSucceed()
public void RangeKey_TypeWithPartitionKeyOnly_ShouldThrow()
{
var type = _fixture.Create<TypeWithPartitionKeyOnly>();
var act = () => PartitionKeyOnly.RangeKey(type.Id);
var act = () => PartitionKeyOnly.PrimaryKeyMarshaller.RangeKey(type.Id);
act.Should().Throw<InvalidOperationException>();
}

Expand All @@ -41,23 +41,23 @@ public void RangeKey_TypeWithPartitionKeyOnly_ShouldThrow()
[InlineData("abc", "dfg")]
public void Keys_TypeWithPartitionKeyOnly_ShouldThrow(string partitionKey, string rangeKey)
{
var act = () => PartitionKeyOnly.Keys(partitionKey, rangeKey);
var act = () => PartitionKeyOnly.PrimaryKeyMarshaller.Keys(partitionKey, rangeKey);
act.Should().Throw<InvalidOperationException>();
}

[Fact]
public void PartitionKey_TypeWithRangeKeyOnly_ShouldThrow()
{
var type = _fixture.Create<TypeWithRangeKeyOnly>();
var act = () => TypeWithRangeOnly.PartitionKey(type.Id);
var act = () => TypeWithRangeOnly.PrimaryKeyMarshaller.PartitionKey(type.Id);
act.Should().Throw<InvalidOperationException>();
}

[Fact]
public void RangeKey_TypeWithRangeKeyOnly_ShouldThrow()
{
var type = _fixture.Create<TypeWithRangeKeyOnly>();
var act = () => TypeWithRangeOnly.RangeKey(type.Id);
var act = () => TypeWithRangeOnly.PrimaryKeyMarshaller.RangeKey(type.Id);

act.Should().Throw<InvalidOperationException>();
}
Expand All @@ -69,23 +69,23 @@ public void RangeKey_TypeWithRangeKeyOnly_ShouldThrow()
[InlineData("abc", "dfg")]
public void Keys_TypeWithRangeKeyOnly_ShouldThrow(string partitionKey, string rangeKey)
{
var act = () => TypeWithRangeOnly.Keys(partitionKey, rangeKey);
var act = () => TypeWithRangeOnly.PrimaryKeyMarshaller.Keys(partitionKey, rangeKey);
act.Should().Throw<InvalidOperationException>();
}

[Fact]
public void PartitionKey_TypeWithoutKeys_ShouldThrow()
{
var type = _fixture.Create<TypeWithKeys>();
var act = () => TypeWithoutKeys.PartitionKey(type.Id);
var act = () => TypeWithoutKeys.PrimaryKeyMarshaller.PartitionKey(type.Id);
act.Should().Throw<InvalidOperationException>();
}

[Fact]
public void RangeKey_TypeWithoutKeys_ShouldSucceed()
{
var type = _fixture.Create<TypeWithoutKeys>();
var act = () => TypeWithoutKeys.RangeKey(type.Id);
var act = () => TypeWithoutKeys.PrimaryKeyMarshaller.RangeKey(type.Id);
act.Should().Throw<InvalidOperationException>();
}

Expand All @@ -96,7 +96,7 @@ public void RangeKey_TypeWithoutKeys_ShouldSucceed()
[InlineData("abc", "dfg")]
public void Keys_TypeWithoutKeys_ShouldThrow(string partitionKey, string rangeKey)
{
var act = () => TypeWithoutKeys.Keys(partitionKey, rangeKey);
var act = () => TypeWithoutKeys.PrimaryKeyMarshaller.Keys(partitionKey, rangeKey);
act.Should().Throw<InvalidOperationException>();
}

Expand All @@ -106,6 +106,7 @@ public void PartitionKey_TypeWithKeys_ShouldSucceed()
{
var type = _fixture.Create<TypeWithKeys>();
TypeWithKeys
.PrimaryKeyMarshaller
.PartitionKey(type.Id)
.Should().SatisfyRespectively(x =>
{
Expand All @@ -118,7 +119,7 @@ public void PartitionKey_TypeWithKeys_ShouldSucceed()
public void RangeKey_TypeWithKeys_ShouldSucceed()
{
var type = _fixture.Create<TypeWithKeys>();
TypeWithKeys.RangeKey(type.RangeKey).Should().SatisfyRespectively(x =>
TypeWithKeys.PrimaryKeyMarshaller.RangeKey(type.RangeKey).Should().SatisfyRespectively(x =>
{
x.Key.Should().Be(nameof(type.RangeKey));
x.Value.S.Should().Be(type.RangeKey);
Expand All @@ -130,6 +131,7 @@ public void Keys_ValidTypeWithKeys_ShouldSucceed()
{
var keys = _fixture.Create<TypeWithKeys>();
TypeWithKeys
.PrimaryKeyMarshaller
.Keys(keys.Id, keys.RangeKey)
.Should()
.SatisfyRespectively(x =>
Expand All @@ -150,7 +152,7 @@ public void Keys_ValidTypeWithKeys_ShouldSucceed()
[InlineData(1, 2)]
public void Keys_InvalidTypeWithKeys_ShouldThrow(object partitionKey, object rangeKey)
{
var act = () => TypeWithKeys.Keys(partitionKey, rangeKey);
var act = () => TypeWithKeys.PrimaryKeyMarshaller.Keys(partitionKey, rangeKey);
act.Should().Throw<DynamoDBMarshallingException>();
}

Expand All @@ -163,7 +165,7 @@ public void Keys_InvalidTypeWithKeys_ShouldThrow(object partitionKey, object ran
[InlineData('A')]
public void PartitionKey_InvalidTypes_ShouldThrow(object key)
{
var act = () => PartitionKeyOnly.PartitionKey(key);
var act = () => PartitionKeyOnly.PrimaryKeyMarshaller.PartitionKey(key);
act.Should().Throw<DynamoDBMarshallingException>();
}

Expand All @@ -176,7 +178,7 @@ public void PartitionKey_InvalidTypes_ShouldThrow(object key)
[InlineData('A')]
public void RangeKey_InvalidTypes_ShouldThrow(object key)
{
var act = () => PartitionKeyOnly.RangeKey(key);
var act = () => PartitionKeyOnly.PrimaryKeyMarshaller.RangeKey(key);
act.Should().Throw<InvalidOperationException>();

}
Expand All @@ -190,7 +192,7 @@ public void RangeKey_InvalidTypes_ShouldThrow(object key)
[InlineData('A')]
public void Keys_InvalidTypes_ShouldThrow(object key)
{
var act = () => PartitionKeyOnly.Keys(key, key);
var act = () => PartitionKeyOnly.PrimaryKeyMarshaller.Keys(key, key);
act.Should().Throw<DynamoDBMarshallingException>();
}
}
Expand Down
5 changes: 5 additions & 0 deletions DynamoDBGenerator.SourceGenerator/Constants.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using DynamoDBGenerator.Attributes;
using DynamoDBGenerator.Exceptions;
using DynamoDBGenerator.Internal;

namespace DynamoDBGenerator.SourceGenerator;

Expand All @@ -11,6 +12,10 @@ public static class Constants
public const string MarshallerConstructorAttributeName = nameof(DynamoDBMarshallerConstructorAttribute);
public const string DynamoDbDocumentPropertyFullname = $"{AssemblyName}.{AttributeNameSpace}.{MarshallerAttributeName}";
public const string MarshallingExceptionName = nameof(DynamoDBMarshallingException);
public const string KeyMarshallerInterFaceName = nameof(IDynamoDBKeyMarshaller);
public const string KeyMarshallerImplementationTypeName = nameof(DynamoDBKeyMarshallerDelegator);
public const string IndexKeyMarshallerInterfaceName = nameof(IDynamoDBIndexKeyMarshaller);
public const string IndexKeyMarshallerImplementationTypeName = nameof(IndexDynamoDBMarshallerDelegator);

public const string NewLine = @"
";
Expand Down
12 changes: 4 additions & 8 deletions DynamoDBGenerator.SourceGenerator/DynamoDbMarshaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,13 +189,10 @@ public string CreateDynamoDbDocumentProperty(Accessibility accessibility)
var valueTrackerTypeName = _attributeValueAssignmentNameFactory(_argumentTypeSymbol);
var nameTrackerTypeName = _attributeNameAssignmentNameFactory(_entityTypeSymbol);
var implementInterface =
$@"private readonly string? _index;
public {className}(string? index) => _index = index;
public {nameof(Dictionary<int, int>)}<{nameof(String)}, {nameof(AttributeValue)}> {SerializeName}({rootTypeName} entity) => {_serializationMethodNameFactory(_entityTypeSymbol)}(entity);
$@"public {nameof(Dictionary<int, int>)}<{nameof(String)}, {nameof(AttributeValue)}> {SerializeName}({rootTypeName} entity) => {_serializationMethodNameFactory(_entityTypeSymbol)}(entity);
public {rootTypeName} {DeserializeName}({nameof(Dictionary<int, int>)}<{nameof(String)}, {nameof(AttributeValue)}> entity) => {_deserializationMethodNameFactory(_entityTypeSymbol)}(entity);
public {nameof(Dictionary<int, int>)}<{nameof(String)}, {nameof(AttributeValue)}> {KeysName}(object partitionKey, object rangeKey) => {_keysMethodNameFactory(_entityTypeSymbol)}(partitionKey, rangeKey, true, true, _index);
public {nameof(Dictionary<int, int>)}<{nameof(String)}, {nameof(AttributeValue)}> {RangeKeyName}(object rangeKey) => {_keysMethodNameFactory(_entityTypeSymbol)}(null, rangeKey, false, true, _index);
public {nameof(Dictionary<int, int>)}<{nameof(String)}, {nameof(AttributeValue)}> {PartitionKeyName}(object partitionKey) => {_keysMethodNameFactory(_entityTypeSymbol)}(partitionKey, null, true, false, _index);
public {Constants.KeyMarshallerInterFaceName} PrimaryKeyMarshaller {{ get; }} = new {Constants.KeyMarshallerImplementationTypeName}({_keysMethodNameFactory(_entityTypeSymbol)});
public {Constants.IndexKeyMarshallerInterfaceName} IndexKeyMarshaller(string index) => new {Constants.IndexKeyMarshallerImplementationTypeName}({_keysMethodNameFactory(_entityTypeSymbol)}, index);
public {className}.{valueTrackerTypeName} {ValueTrackerName}()
{{
var number = 0;
Expand Down Expand Up @@ -223,8 +220,7 @@ public string CreateDynamoDbDocumentProperty(Accessibility accessibility)
);

return
$@"{accessibility.ToCode()} {@interface} {_publicAccessPropertyName} {{ get; }} = new {className}(null);
{accessibility.ToCode()} {@interface} {_publicAccessPropertyName}WithIndex(string index) => new {className}(index);
$@"{accessibility.ToCode()} {@interface} {_publicAccessPropertyName} {{ get; }} = new {className}();
{@class}";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public static string CreateNamespace(this ITypeSymbol type, in string content, T
using DynamoDBGenerator;
using DynamoDBGenerator.Attributes;
using DynamoDBGenerator.Exceptions;
using DynamoDBGenerator.Internal;
{(nameSpace is null ? null : $@"namespace {nameSpace}
{{")}
Expand Down
1 change: 1 addition & 0 deletions DynamoDBGenerator/DynamoDBClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using DynamoDBGenerator.Extensions;
using DynamoDBGenerator.Internal;
namespace DynamoDBGenerator;

internal class DynamoDBClient<T, TArg, TReferences, TArgumentReferences> : IDynamoDBClient<T, TArg, TReferences, TArgumentReferences>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using DynamoDBGenerator.Internal;
namespace DynamoDBGenerator.Extensions;

public static class DynamoDBMarshallerExtensions
Expand Down
6 changes: 5 additions & 1 deletion DynamoDBGenerator/IDynamoDBKeyMarshaller.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.Model;
namespace DynamoDBGenerator;

Expand Down Expand Up @@ -30,4 +29,9 @@ public interface IDynamoDBKeyMarshaller
/// <param name="key">The range key to be marshalled.</param>
/// <returns>A Dictionary containing marshalled AttributeValues for the range key.</returns>
public Dictionary<string, AttributeValue> RangeKey(object key);
}

public interface IDynamoDBIndexKeyMarshaller : IDynamoDBKeyMarshaller
{
public string Index { get; }
}
5 changes: 4 additions & 1 deletion DynamoDBGenerator/IDynamoDBMarshaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace DynamoDBGenerator;
/// <typeparam name="TArg">The type of argument used for marshalling.</typeparam>
/// <typeparam name="TEntityAttributeNameTracker">The type for tracking attribute names related to <typeparamref name="TEntity"/>.</typeparam>
/// <typeparam name="TArgumentAttributeValueTracker">The type for tracking argument attribute values related to <typeparamref name="TArg"/>.</typeparam>
public interface IDynamoDBMarshaller<TEntity, in TArg, out TEntityAttributeNameTracker, out TArgumentAttributeValueTracker> : IDynamoDBKeyMarshaller
public interface IDynamoDBMarshaller<TEntity, in TArg, out TEntityAttributeNameTracker, out TArgumentAttributeValueTracker>
where TEntityAttributeNameTracker : IExpressionAttributeNameTracker
where TArgumentAttributeValueTracker : IExpressionAttributeValueTracker<TArg>
{
Expand Down Expand Up @@ -39,6 +39,9 @@ public interface IDynamoDBMarshaller<TEntity, in TArg, out TEntityAttributeNameT
/// <param name="attributes">The AttributeValues to be deserialized.</param>
/// <returns>An object of type <typeparamref name="TEntity"/>.</returns>
public TEntity Unmarshall(Dictionary<string, AttributeValue> attributes);

public IDynamoDBKeyMarshaller PrimaryKeyMarshaller { get; }
public IDynamoDBIndexKeyMarshaller IndexKeyMarshaller(string index);
}

/// <summary>
Expand Down
20 changes: 20 additions & 0 deletions DynamoDBGenerator/Internal/DynamoDBKeyMarshallerDelegator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2.Model;
namespace DynamoDBGenerator.Internal;

/// <summary>
/// This is an internal API that supports the source generator and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new version.
/// </summary>
public sealed class DynamoDBKeyMarshallerDelegator : IDynamoDBKeyMarshaller

{
private readonly Func<object?, object?, bool, bool, string?, Dictionary<string, AttributeValue>> _fn;
public DynamoDBKeyMarshallerDelegator(Func<object?, object?, bool, bool, string?, Dictionary<string, AttributeValue>> fn) => _fn = fn;
public Dictionary<string, AttributeValue> Keys(object partitionKey, object rangeKey) => _fn(partitionKey, rangeKey, true, true, null);
public Dictionary<string, AttributeValue> PartitionKey(object key) => _fn(key, null, true, false, null);
public Dictionary<string, AttributeValue> RangeKey(object key) => _fn(null, key, false, true, null);
}
Loading

0 comments on commit 4751bdb

Please sign in to comment.