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

Fixes #1059: Support for reading/writing spatial WKB #3173

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
8 changes: 8 additions & 0 deletions src/Microsoft.Spatial/DataServicesSpatialImplementation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,13 @@ public override SpatialPipeline CreateValidator()
{
return new ForwardingSegment(new SpatialValidatorImplementation());
}

/// <summary> Creates a WellKnownBinaryFormatter for this implementation.</summary>
/// <returns>The WellKnownBinaryFormatter created.</returns>
/// <param name="settings">Controls the writing settings.</param>
public override WellKnownBinaryFormatter CreateWellKnownBinaryFormatter(WellKnownBinaryWriterSettings settings)
{
return new WellKnownBinaryFormatterImplementation(this, settings);
}
}
}
20 changes: 19 additions & 1 deletion src/Microsoft.Spatial/PublicAPI/net8.0/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1 +1,19 @@

abstract Microsoft.Spatial.SpatialImplementation.CreateWellKnownBinaryFormatter(Microsoft.Spatial.WellKnownBinaryWriterSettings settings) -> Microsoft.Spatial.WellKnownBinaryFormatter
Microsoft.Spatial.ByteOrder
Microsoft.Spatial.ByteOrder.BigEndian = 0 -> Microsoft.Spatial.ByteOrder
Microsoft.Spatial.ByteOrder.LittleEndian = 1 -> Microsoft.Spatial.ByteOrder
Microsoft.Spatial.WellKnownBinaryFormatter
Microsoft.Spatial.WellKnownBinaryFormatter.WellKnownBinaryFormatter(Microsoft.Spatial.SpatialImplementation creator) -> void
Microsoft.Spatial.WellKnownBinaryWriterSettings
Microsoft.Spatial.WellKnownBinaryWriterSettings.HandleM.get -> bool
Microsoft.Spatial.WellKnownBinaryWriterSettings.HandleM.set -> void
Microsoft.Spatial.WellKnownBinaryWriterSettings.HandleSRID.get -> bool
Microsoft.Spatial.WellKnownBinaryWriterSettings.HandleSRID.set -> void
Microsoft.Spatial.WellKnownBinaryWriterSettings.HandleZ.get -> bool
Microsoft.Spatial.WellKnownBinaryWriterSettings.HandleZ.set -> void
Microsoft.Spatial.WellKnownBinaryWriterSettings.IsoWKB.get -> bool
Microsoft.Spatial.WellKnownBinaryWriterSettings.IsoWKB.set -> void
Microsoft.Spatial.WellKnownBinaryWriterSettings.Order.get -> Microsoft.Spatial.ByteOrder
Microsoft.Spatial.WellKnownBinaryWriterSettings.Order.set -> void
Microsoft.Spatial.WellKnownBinaryWriterSettings.WellKnownBinaryWriterSettings() -> void
static Microsoft.Spatial.WellKnownBinaryFormatter.Create(Microsoft.Spatial.WellKnownBinaryWriterSettings settings) -> Microsoft.Spatial.WellKnownBinaryFormatter
90 changes: 90 additions & 0 deletions src/Microsoft.Spatial/SRResources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions src/Microsoft.Spatial/SRResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,36 @@
<data name="WellKnownText_TooManyDimensions" xml:space="preserve">
<value>The WellKnownTextReader is configured to allow only two dimensions, and a third dimension was encountered.</value>
</data>
<data name="WellKnownBinary_NotSupportedSpatial" xml:space="preserve">
<value>The WKB writer: Spatial type "{0}" is not supported.</value>
</data>
<data name="WellKnownBinary_InvalidSubSpatial" xml:space="preserve">
<value>The WKB writer: Invalid to begin a "{0}" under "{1}", Details: "{2}".</value>
</data>
<data name="WellKnownBinary_InvalidBeginOrEndFigureOrAddLine" xml:space="preserve">
<value>The WKB writer: Invalid to "{0}" without specify the spatial type. Please call BeginGeometry(), or beginGeography() first.</value>
</data>
<data name="WellKnownBinary_InvalidBeginFigureOnSpatial" xml:space="preserve">
<value>The WKB writer: Invalid to begin a figure for spatial type "{0}".</value>
</data>
<data name="WellKnownBinary_InvalidBeginFigureWithoutEndingPrevious" xml:space="preserve">
<value>The WKB writer: Invalid to begin a new figure "{0}" without ending the previou figure.</value>
</data>
<data name="WellKnownBinary_InvalidAddLineTo" xml:space="preserve">
<value>The WKB writer: Invalid to AddLineTo for "{0}".{1}</value>
</data>
<data name="WellKnownBinary_InvalidEndFigure" xml:space="preserve">
<value>The WKB writer: Invalid to end figure on "{0}".{1}</value>
</data>
<data name="WellKnownBinary_InvalidEndGeo" xml:space="preserve">
<value>The WKB writer: Invalid to end spatial type "{0}".{1}</value>
</data>
<data name="WellKnownBinary_ByteLengthNotEnough" xml:space="preserve">
<value>The WKB reader is reading a "{0}" value with "{1}" bytes expected but only get "{2}" bytes.</value>
</data>
<data name="WellKnownBinary_UnknownByteOrder" xml:space="preserve">
<value>The WKB reader: the byte order '{0}' is unknown. It should be 0x00 (BigEndian) and 0x01 (LittleEndian).</value>
</data>
<data name="Validator_SridMismatch" xml:space="preserve">
<value>Invalid spatial data: An instance of spatial type can have only one unique CoordinateSystem for all of its coordinates.</value>
</data>
Expand Down
5 changes: 5 additions & 0 deletions src/Microsoft.Spatial/Spatial/SpatialImplementation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ public abstract SpatialOperations Operations
/// <param name="allowOnlyTwoDimensions">Controls the writing and reading of the Z and M dimension.</param>
public abstract WellKnownTextSqlFormatter CreateWellKnownTextSqlFormatter(bool allowOnlyTwoDimensions);

/// <summary> Creates a WellKnownBinaryFormatter for this implementation.</summary>
/// <returns>The WellKnownBinaryFormatter created.</returns>
/// <param name="settings">Controls the writing settings.</param>
public abstract WellKnownBinaryFormatter CreateWellKnownBinaryFormatter(WellKnownBinaryWriterSettings settings);

/// <summary> Creates a spatial Validator.</summary>
/// <returns>The SpatialValidator created.</returns>
public abstract SpatialPipeline CreateValidator();
Expand Down
147 changes: 147 additions & 0 deletions src/Microsoft.Spatial/WellKnown/BinaryFormatterExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
//---------------------------------------------------------------------
// <copyright file="BinaryFormatterExtensions.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------

namespace Microsoft.Spatial
{
using System;
using System.Buffers.Binary;
using System.IO;

internal static class BinaryFormatterExtensions
{
/// <summary>
/// Writes the double value based on the byte order setting.
/// </summary>
/// <param name="writer">The binary writer.</param>
/// <param name="value">The double value.</param>
/// <param name="order">The byte order.</param>
public static void Write(this BinaryWriter writer, double value, ByteOrder order)
{
Span<byte> buffer = stackalloc byte[8];
if (order == ByteOrder.LittleEndian)
{
BinaryPrimitives.WriteDoubleLittleEndian(buffer, value);
}
else
{
BinaryPrimitives.WriteDoubleBigEndian(buffer, value);
}

writer.Write(buffer);
}

/// <summary>
/// Writes the uint value based on the byte order setting.
/// </summary>
/// <param name="writer">The binary writer.</param>
/// <param name="value">The uint value.</param>
/// <param name="order">The byte order.</param>
public static void Write(this BinaryWriter writer, uint value, ByteOrder order)
{
Span<byte> buffer = stackalloc byte[4];
if (order == ByteOrder.LittleEndian)
{
BinaryPrimitives.WriteUInt32LittleEndian(buffer, value);
}
else
{
BinaryPrimitives.WriteUInt32BigEndian(buffer, value);
}

writer.Write(buffer);
}

/// <summary>
/// Writes the int value based on the byte order setting.
/// </summary>
/// <param name="writer">The binary writer.</param>
/// <param name="value">The int value.</param>
/// <param name="order">The byte order.</param>
public static void Write(this BinaryWriter writer, int value, ByteOrder order)
{
Span<byte> buffer = stackalloc byte[4];
if (order == ByteOrder.LittleEndian)
{
BinaryPrimitives.WriteInt32LittleEndian(buffer, value);
}
else
{
BinaryPrimitives.WriteInt32BigEndian(buffer, value);
}

writer.Write(buffer);
}

/// <summary>
/// Reads the uint value from reader based on the byte order setting.
/// </summary>
/// <param name="reader">The binary reader.</param>
/// <param name="order">The byte order.</param>
/// <returns>The uint value read from the reader.</returns>
public static uint ReadUInt32(this BinaryReader reader, ByteOrder order)
{
Span<byte> buffer = stackalloc byte[4];
int num = reader.Read(buffer);
if (num != 4)
{
throw new FormatException(Error.Format(SRResources.WellKnownBinary_ByteLengthNotEnough, "UInt32", 4, num));
}

if (order == ByteOrder.LittleEndian)
{
return BinaryPrimitives.ReadUInt32LittleEndian(buffer);
}

return BinaryPrimitives.ReadUInt32BigEndian(buffer);
}

/// <summary>
/// Reads the int value from reader based on the byte order setting.
/// </summary>
/// <param name="reader">The binary reader.</param>
/// <param name="order">The byte order.</param>
/// <returns>The int value read from the reader.</returns>
public static int ReadInt32(this BinaryReader reader, ByteOrder order)
{
Span<byte> buffer = stackalloc byte[4];
int num = reader.Read(buffer);
if (num != 4)
{
throw new FormatException(Error.Format(SRResources.WellKnownBinary_ByteLengthNotEnough, "Int32", 4, num));
}

if (order == ByteOrder.LittleEndian)
{
return BinaryPrimitives.ReadInt32LittleEndian(buffer);
}

return BinaryPrimitives.ReadInt32BigEndian(buffer);
}

/// <summary>
/// Reads the double value from reader based on the byte order setting.
/// </summary>
/// <param name="reader">The binary reader.</param>
/// <param name="order">The byte order.</param>
/// <returns>The double value read from the reader.</returns>
public static double ReadDouble(this BinaryReader reader, ByteOrder order)
{
Span<byte> buffer = stackalloc byte[8];
int num = reader.Read(buffer);
if (num != 8)
{
throw new FormatException(Error.Format(SRResources.WellKnownBinary_ByteLengthNotEnough, "Double", 8, num));
}

if (order == ByteOrder.LittleEndian)
{
return BinaryPrimitives.ReadDoubleLittleEndian(buffer);
}

return BinaryPrimitives.ReadDoubleBigEndian(buffer);
}
}
}
24 changes: 24 additions & 0 deletions src/Microsoft.Spatial/WellKnown/ByteOrder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//---------------------------------------------------------------------
// <copyright file="ByteOrder.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------

namespace Microsoft.Spatial
{
/// <summary>
/// Byte order
/// </summary>
public enum ByteOrder
{
/// <summary>
/// Big Endian
/// </summary>
BigEndian = 0x00,

/// <summary>
/// Little Endian
/// </summary>
LittleEndian = 0x01,
}
}
32 changes: 32 additions & 0 deletions src/Microsoft.Spatial/WellKnown/WellKnownBinaryFormatter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//---------------------------------------------------------------------
// <copyright file="WellKnownBinaryFormatter.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------

namespace Microsoft.Spatial
{
using System.IO;

/// <summary>
/// The object to move spatial types to and from the WellKnownBinary format
/// </summary>
public abstract class WellKnownBinaryFormatter : SpatialFormatter<Stream, Stream>
{
/// <summary>
/// Initializes a new instance of the <see cref="WellKnownBinaryFormatter"/> class.
/// </summary>
/// <param name="creator">The implementation that created this instance.</param>
protected WellKnownBinaryFormatter(SpatialImplementation creator)
: base(creator)
{
}

/// <summary>
/// Creates the implementation of the formatter.
/// </summary>
/// <returns>Returns the created <see cref="WellKnownBinaryFormatter"> implementation.</returns>
public static WellKnownBinaryFormatter Create(WellKnownBinaryWriterSettings settings)
=> SpatialImplementation.CurrentImplementation.CreateWellKnownBinaryFormatter(settings);
}
}
Loading
Loading