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

Support for ReadOnlyMemory<char> cells #52

Merged
merged 6 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</ItemGroup>
<ItemGroup>
<PackageVersion Include="BenchmarkDotNet" Version="0.13.12" />
<PackageVersion Include="Bogus" Version="35.5.0" />
<PackageVersion Include="Bogus" Version="35.5.1" />
<PackageVersion Include="ClosedXML" Version="0.102.2" />
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
<PackageVersion Include="DocumentFormat.OpenXml" Version="2.20.0" />
Expand All @@ -32,8 +32,9 @@
<PackageVersion Include="System.IO.Compression" Version="4.3.0" />
<PackageVersion Include="System.Memory" Version="4.5.5" />
<PackageVersion Include="Verify.SourceGenerators" Version="2.2.0" />
<PackageVersion Include="Verify.Xunit" Version="24.1.0" />
<PackageVersion Include="xunit" Version="2.7.1" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.8" />
<PackageVersion Include="Verify.Xunit" Version="24.2.0" />
<PackageVersion Include="xunit" Version="2.8.0" />
<PackageVersion Include="xunit.assert" Version="2.8.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.0" />
</ItemGroup>
</Project>
8 changes: 8 additions & 0 deletions SpreadCheetah.Test/Helpers/CellFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ internal static class CellFactory
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};

public static object Create(CellType type, ReadOnlyMemory<char> value) => type switch
{
CellType.Cell => new Cell(value),
CellType.DataCell => new DataCell(value),
CellType.StyledCell => new StyledCell(value, null),
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};

public static object Create(CellType type, string? value, StyleId? styleId) => type switch
{
CellType.Cell => new Cell(value, styleId),
Expand Down
1 change: 1 addition & 0 deletions SpreadCheetah.Test/SpreadCheetah.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\SpreadCheetah.TestHelpers\SpreadCheetah.TestHelpers.csproj" />
<ProjectReference Include="..\SpreadCheetah\SpreadCheetah.csproj" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace SpreadCheetah
public Cell(double value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(int value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(long value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(System.ReadOnlyMemory<char> value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(float value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(bool? value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(decimal? value, SpreadCheetah.Styling.StyleId? styleId = null) { }
Expand All @@ -30,6 +31,7 @@ namespace SpreadCheetah
public Cell(SpreadCheetah.Formula formula, double cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, int cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, long cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, System.ReadOnlyMemory<char> cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, float cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, bool? cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, decimal? cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
Expand All @@ -48,6 +50,7 @@ namespace SpreadCheetah
public DataCell(double value) { }
public DataCell(int value) { }
public DataCell(long value) { }
public DataCell(System.ReadOnlyMemory<char> value) { }
public DataCell(float value) { }
public DataCell(bool? value) { }
public DataCell(decimal? value) { }
Expand Down Expand Up @@ -137,6 +140,7 @@ namespace SpreadCheetah
public StyledCell(double value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(int value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(long value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(System.ReadOnlyMemory<char> value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(float value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(bool? value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(decimal? value, SpreadCheetah.Styling.StyleId? styleId) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace SpreadCheetah
public Cell(double value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(int value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(long value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(System.ReadOnlyMemory<char> value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(float value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(bool? value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(decimal? value, SpreadCheetah.Styling.StyleId? styleId = null) { }
Expand All @@ -30,6 +31,7 @@ namespace SpreadCheetah
public Cell(SpreadCheetah.Formula formula, double cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, int cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, long cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, System.ReadOnlyMemory<char> cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, float cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, bool? cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, decimal? cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
Expand All @@ -48,6 +50,7 @@ namespace SpreadCheetah
public DataCell(double value) { }
public DataCell(int value) { }
public DataCell(long value) { }
public DataCell(System.ReadOnlyMemory<char> value) { }
public DataCell(float value) { }
public DataCell(bool? value) { }
public DataCell(decimal? value) { }
Expand Down Expand Up @@ -137,6 +140,7 @@ namespace SpreadCheetah
public StyledCell(double value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(int value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(long value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(System.ReadOnlyMemory<char> value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(float value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(bool? value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(decimal? value, SpreadCheetah.Styling.StyleId? styleId) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace SpreadCheetah
public Cell(double value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(int value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(long value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(System.ReadOnlyMemory<char> value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(float value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(bool? value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(decimal? value, SpreadCheetah.Styling.StyleId? styleId = null) { }
Expand All @@ -30,6 +31,7 @@ namespace SpreadCheetah
public Cell(SpreadCheetah.Formula formula, double cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, int cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, long cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, System.ReadOnlyMemory<char> cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, float cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, bool? cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, decimal? cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
Expand All @@ -48,6 +50,7 @@ namespace SpreadCheetah
public DataCell(double value) { }
public DataCell(int value) { }
public DataCell(long value) { }
public DataCell(System.ReadOnlyMemory<char> value) { }
public DataCell(float value) { }
public DataCell(bool? value) { }
public DataCell(decimal? value) { }
Expand Down Expand Up @@ -137,6 +140,7 @@ namespace SpreadCheetah
public StyledCell(double value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(int value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(long value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(System.ReadOnlyMemory<char> value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(float value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(bool? value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(decimal? value, SpreadCheetah.Styling.StyleId? styleId) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace SpreadCheetah
public Cell(double value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(int value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(long value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(System.ReadOnlyMemory<char> value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(float value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(bool? value, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(decimal? value, SpreadCheetah.Styling.StyleId? styleId = null) { }
Expand All @@ -29,6 +30,7 @@ namespace SpreadCheetah
public Cell(SpreadCheetah.Formula formula, double cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, int cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, long cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, System.ReadOnlyMemory<char> cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, float cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, bool? cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
public Cell(SpreadCheetah.Formula formula, decimal? cachedValue, SpreadCheetah.Styling.StyleId? styleId = null) { }
Expand All @@ -47,6 +49,7 @@ namespace SpreadCheetah
public DataCell(double value) { }
public DataCell(int value) { }
public DataCell(long value) { }
public DataCell(System.ReadOnlyMemory<char> value) { }
public DataCell(float value) { }
public DataCell(bool? value) { }
public DataCell(decimal? value) { }
Expand Down Expand Up @@ -136,6 +139,7 @@ namespace SpreadCheetah
public StyledCell(double value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(int value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(long value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(System.ReadOnlyMemory<char> value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(float value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(bool? value, SpreadCheetah.Styling.StyleId? styleId) { }
public StyledCell(decimal? value, SpreadCheetah.Styling.StyleId? styleId) { }
Expand Down
45 changes: 29 additions & 16 deletions SpreadCheetah.Test/Tests/SpreadsheetRowTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using CellType = SpreadCheetah.Test.Helpers.CellType;
using OpenXmlCell = DocumentFormat.OpenXml.Spreadsheet.Cell;
using OpenXmlCellValue = DocumentFormat.OpenXml.Spreadsheet.CellValues;
using SpreadsheetAssert = SpreadCheetah.TestHelpers.Assertions.SpreadsheetAssert;

namespace SpreadCheetah.Test.Tests;

Expand Down Expand Up @@ -117,7 +118,7 @@ await using (var spreadsheet = await Spreadsheet.CreateNewAsync(stream))
"WithNorwegianCharactersÆØÅ",
"With\ud83d\udc4dEmoji",
"With🌉Emoji",
"With\tValid\nControlCharacters",
"With\tValid\r\nControlCharacters",
"WithCharacters\u00a0\u00c9\u00ffBetween160And255",
"",
null);
Expand All @@ -128,24 +129,36 @@ public async Task Spreadsheet_AddRow_CellWithStringValue(string? value, CellType
{
// Arrange
using var stream = new MemoryStream();
await using (var spreadsheet = await Spreadsheet.CreateNewAsync(stream))
{
await spreadsheet.StartWorksheetAsync("Sheet");
var cell = CellFactory.Create(type, value);
await using var spreadsheet = await Spreadsheet.CreateNewAsync(stream);
await spreadsheet.StartWorksheetAsync("Sheet");
var cell = CellFactory.Create(type, value);

// Act
await spreadsheet.AddRowAsync(cell, rowType);
await spreadsheet.FinishAsync();
}
// Act
await spreadsheet.AddRowAsync(cell, rowType);
await spreadsheet.FinishAsync();

// Assert
SpreadsheetAssert.Valid(stream);
using var actual = SpreadsheetDocument.Open(stream, true);
var sheetPart = actual.WorkbookPart!.WorksheetParts.Single();
var actualCell = sheetPart.Worksheet.Descendants<OpenXmlCell>().Single();
OpenXmlCellValue? expectedDataType = value is null ? null : OpenXmlCellValue.InlineString;
Assert.Equal(expectedDataType, actualCell.DataType?.Value);
Assert.Equal(value ?? string.Empty, actualCell.InnerText);
using var sheet = SpreadsheetAssert.SingleSheet(stream);
Assert.Equal(value, sheet["A1"].StringValue);
}

[Theory]
[MemberData(nameof(Strings))]
public async Task Spreadsheet_AddRow_CellWithReadOnlyMemoryOfCharValue(string? value, CellType type, RowCollectionType rowType)
{
// Arrange
using var stream = new MemoryStream();
await using var spreadsheet = await Spreadsheet.CreateNewAsync(stream);
await spreadsheet.StartWorksheetAsync("Sheet");
var cell = CellFactory.Create(type, value.AsMemory());

// Act
await spreadsheet.AddRowAsync(cell, rowType);
await spreadsheet.FinishAsync();

// Assert
using var sheet = SpreadsheetAssert.SingleSheet(stream);
Assert.Equal(value ?? "", sheet["A1"].StringValue);
}

[Theory]
Expand Down
13 changes: 13 additions & 0 deletions SpreadCheetah.TestHelpers/Assertions/ClosedXmlAssertSheet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ namespace SpreadCheetah.TestHelpers.Assertions;
internal sealed class ClosedXmlAssertSheet(XLWorkbook workbook, IXLWorksheet sheet)
: ISpreadsheetAssertSheet
{
public ISpreadsheetAssertCell this[string reference]
{
get
{
if (!SpreadsheetUtility.TryParseColumnName(reference.AsSpan(0, 1), out _))
throw new ArgumentException("Invalid reference.", nameof(reference));
if (!int.TryParse(reference.Substring(1), out var rowNumber))
throw new ArgumentException("Invalid reference. The column name must currently have a single letter.", nameof(reference));

return this[reference.Substring(0, 1), rowNumber];
}
}

public ISpreadsheetAssertCell this[string columnName, int rowNumber]
{
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ namespace SpreadCheetah.TestHelpers.Assertions;

public interface ISpreadsheetAssertSheet : IDisposable
{
ISpreadsheetAssertCell this[string reference] { get; }
ISpreadsheetAssertCell this[string columnName, int rowNumber] { get; }
int CellCount { get; }
int RowCount { get; }
Expand Down
21 changes: 20 additions & 1 deletion SpreadCheetah.TestHelpers/Assertions/SpreadsheetAssert.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using ClosedXML.Excel;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Validation;
using Xunit;

namespace SpreadCheetah.TestHelpers.Assertions;

Expand All @@ -9,11 +12,27 @@ public static ISpreadsheetAssertSheet SingleSheet(Stream stream)
if (stream is null)
throw new ArgumentNullException(nameof(stream));

stream.Position = 0;
Valid(stream);

#pragma warning disable CA2000 // Dispose objects before losing scope
var workbook = new XLWorkbook(stream);
#pragma warning restore CA2000 // Dispose objects before losing scope
var sheet = workbook.Worksheets.Single();
return new ClosedXmlAssertSheet(workbook, sheet);
}

public static void Valid(Stream stream)
{
if (stream is null)
throw new ArgumentNullException(nameof(stream));

stream.Position = 0;

using var document = SpreadsheetDocument.Open(stream, false);
var validator = new OpenXmlValidator();
var errors = validator.Validate(document);
Assert.Empty(errors);

stream.Position = 0;
}
}
1 change: 1 addition & 0 deletions SpreadCheetah.TestHelpers/SpreadCheetah.TestHelpers.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

<ItemGroup>
<PackageReference Include="ClosedXML" />
<PackageReference Include="xunit.assert" />
</ItemGroup>

<ItemGroup>
Expand Down
14 changes: 14 additions & 0 deletions SpreadCheetah/Cell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@
{
}

/// <summary>
/// Initializes a new instance of the <see cref="Cell"/> struct with a text value and an optional style.
/// </summary>
public Cell(ReadOnlyMemory<char> value, StyleId? styleId = null) : this(new DataCell(value), null, styleId)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="Cell"/> struct with an integer value and an optional style.
/// </summary>
Expand Down Expand Up @@ -154,6 +161,13 @@
{
}

/// <summary>
/// Initializes a new instance of the <see cref="Cell"/> struct with a text formula, a cached value for the formula, and an optional style.
/// </summary>
public Cell(Formula formula, ReadOnlyMemory<char> cachedValue, StyleId? styleId = null) : this(new DataCell(cachedValue), formula, styleId)
{
}

Check warning on line 169 in SpreadCheetah/Cell.cs

View check run for this annotation

Codecov / codecov/patch

SpreadCheetah/Cell.cs#L167-L169

Added lines #L167 - L169 were not covered by tests

/// <summary>
/// Initializes a new instance of the <see cref="Cell"/> struct with a number formula, a cached value for the formula, and an optional style.
/// </summary>
Expand Down
4 changes: 3 additions & 1 deletion SpreadCheetah/CellValueWriters/CellValueWriter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using SpreadCheetah.CellValueWriters.Boolean;
using SpreadCheetah.CellValueWriters.Characters;
using SpreadCheetah.CellValueWriters.Number;
using SpreadCheetah.CellValueWriters.Time;
using SpreadCheetah.CellWriters;
Expand All @@ -20,7 +21,8 @@ internal abstract class CellValueWriter
new NullDateTimeCellValueWriter(),
new DateTimeCellValueWriter(),
new FalseBooleanCellValueWriter(),
new TrueBooleanCellValueWriter()
new TrueBooleanCellValueWriter(),
new ReadOnlyMemoryOfCharCellValueWriter()
];

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
3 changes: 2 additions & 1 deletion SpreadCheetah/CellValueWriters/CellWriterType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ internal enum CellWriterType : byte
NullDateTime = 5,
DateTime = 6,
FalseBoolean = 7,
TrueBoolean = 8
TrueBoolean = 8,
ReadOnlyMemoryOfChar = 9
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using SpreadCheetah.CellValues;

namespace SpreadCheetah.CellValueWriters.Characters;

internal sealed class ReadOnlyMemoryOfCharCellValueWriter : StringCellValueWriterBase
{
protected override ReadOnlySpan<char> GetSpan(in CellValue cell) => cell.Memory.Span;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using SpreadCheetah.CellValues;

namespace SpreadCheetah.CellValueWriters.Characters;

internal sealed class StringCellValueWriter : StringCellValueWriterBase
{
protected override ReadOnlySpan<char> GetSpan(in CellValue cell) => cell.StringOrPrimitive.StringValue.AsSpan();
}
Loading
Loading