SQLServer

Library that type-ifies some Microsoft SQL Server concepts.
git clone https://git.philomathiclife.com/repos/SQLServer
Log | Files | Refs | README

commit 6386fb5f8d2b24b0a2e629b4d661cd84bfc9431e
parent b5245a6e6c4789c23b35196bda10a1aa5b7b9a8a
Author: Zack Newman <zack@philomathiclife.com>
Date:   Tue, 21 Mar 2023 18:57:53 -0600

made IDataType subtypes implement IBinDeserializable<TSelf>

Diffstat:
MIDataType.cs | 856++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 720 insertions(+), 136 deletions(-)

diff --git a/IDataType.cs b/IDataType.cs @@ -58,7 +58,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 40)] - public readonly struct any: ISum<Unit, long, byte[], bool, string, System.DateTime, SqlDateTime, System.DateTime, System.DateTimeOffset, SqlDecimal, double, byte[], int, SqlMoney, string, string, string, float, SqlDateTime, short, SqlMoney, sql_variant, string, System.TimeSpan, byte, System.Guid, byte[], string, string>, IInto<string>, IInto<any> { + public readonly struct any: ISum<Unit, long, byte[], bool, string, System.DateTime, SqlDateTime, System.DateTime, System.DateTimeOffset, SqlDecimal, double, byte[], int, SqlMoney, string, string, string, float, SqlDateTime, short, SqlMoney, sql_variant, string, System.TimeSpan, byte, System.Guid, byte[], string, string>, IInto<string>, IInto<any>, IBinDeserializable<any> { #region Type-level Constructors #endregion @@ -86,34 +86,34 @@ namespace SQLServer { #region Type-level Fields public static readonly any NULL = new(); - static readonly Fn<long, any> fn_bigint = (x) => new(x); - static readonly Fn<byte[], any> fn_binary = (x) => new(Tag.binary, x); - static readonly Fn<bool, any> fn_bit = (x) => new(x); - static readonly Fn<string, any> fn_char = (x) => new(Tag.@char, x); - static readonly Fn<System.DateTime, any> fn_date = (x) => new(x); - static readonly Fn<SqlDateTime, any> fn_datetime = (x) => new(Tag.datetime, x); - static readonly Fn<System.DateTime, any> fn_datetime2 = (x) => new(x); - static readonly Fn<System.DateTimeOffset, any> fn_datetimeoffset = (x) => new(x); - static readonly Fn<SqlDecimal, any> fn_decimal = (x) => new(x); - static readonly Fn<double, any> fn_float = (x) => new(x); - static readonly Fn<byte[], any> fn_image = (x) => new(Tag.image, x); - static readonly Fn<int, any> fn_int = (x) => new(x); - static readonly Fn<SqlMoney, any> fn_money = (x) => new(Tag.money, x); - static readonly Fn<string, any> fn_nchar = (x) => new(Tag.nchar, x); - static readonly Fn<string, any> fn_ntext = (x) => new(Tag.ntext, x); - static readonly Fn<string, any> fn_nvarchar = (x) => new(Tag.nvarchar, x); - static readonly Fn<float, any> fn_real = (x) => new(x); - static readonly Fn<SqlDateTime, any> fn_smalldatetime = (x) => new(Tag.smalldatetime, x); - static readonly Fn<short, any> fn_smallint = (x) => new(x); - static readonly Fn<SqlMoney, any> fn_smallmoney = (x) => new(Tag.smallmoney, x); + static readonly Fn<bigint, any> fn_bigint = (x) => new(x.Value); + static readonly Fn<binary, any> fn_binary = (x) => new(Tag.binary, x.Value!); + static readonly Fn<bit, any> fn_bit = (x) => new(x.Value); + static readonly Fn<@char, any> fn_char = (x) => new(Tag.@char, x.Value!); + static readonly Fn<date, any> fn_date = (x) => new(x.Value); + static readonly Fn<datetime, any> fn_datetime = (x) => new(Tag.datetime, x.Value); + static readonly Fn<datetime2, any> fn_datetime2 = (x) => new(x.Value); + static readonly Fn<datetimeoffset, any> fn_datetimeoffset = (x) => new(x.Value); + static readonly Fn<@decimal, any> fn_decimal = (x) => new(x.Value); + static readonly Fn<@float, any> fn_float = (x) => new(x.Value); + static readonly Fn<image, any> fn_image = (x) => new(Tag.image, x.Value!); + static readonly Fn<@int, any> fn_int = (x) => new(x.Value); + static readonly Fn<money, any> fn_money = (x) => new(Tag.money, x.Value); + static readonly Fn<nchar, any> fn_nchar = (x) => new(Tag.nchar, x.Value!); + static readonly Fn<ntext, any> fn_ntext = (x) => new(Tag.ntext, x.Value!); + static readonly Fn<nvarchar, any> fn_nvarchar = (x) => new(Tag.nvarchar, x.Value!); + static readonly Fn<real, any> fn_real = (x) => new(x.Value); + static readonly Fn<smalldatetime, any> fn_smalldatetime = (x) => new(Tag.smalldatetime, x.Value); + static readonly Fn<smallint, any> fn_smallint = (x) => new(x.Value); + static readonly Fn<smallmoney, any> fn_smallmoney = (x) => new(Tag.smallmoney, x.Value); static readonly Fn<sql_variant, any> fn_sql_variant = (x) => new(x); - static readonly Fn<string, any> fn_text = (x) => new(Tag.text, x); - static readonly Fn<System.TimeSpan, any> fn_time = (x) => new(x); - static readonly Fn<byte, any> fn_tinyint = (x) => new(x); - static readonly Fn<System.Guid, any> fn_uniqueidentifier = (x) => new(x); - static readonly Fn<byte[], any> fn_varbinary = (x) => new(Tag.varbinary, x); - static readonly Fn<string, any> fn_varchar = (x) => new(Tag.varchar, x); - static readonly Fn<string, any> fn_xml = (x) => new(Tag.xml, x); + static readonly Fn<text, any> fn_text = (x) => new(Tag.text, x.Value!); + static readonly Fn<time, any> fn_time = (x) => new(x.Value); + static readonly Fn<tinyint, any> fn_tinyint = (x) => new(x.Value); + static readonly Fn<uniqueidentifier, any> fn_uniqueidentifier = (x) => new(x.Value); + static readonly Fn<varbinary, any> fn_varbinary = (x) => new(Tag.varbinary, x.Value!); + static readonly Fn<varchar, any> fn_varchar = (x) => new(Tag.varchar, x.Value!); + static readonly Fn<xml, any> fn_xml = (x) => new(Tag.xml, x.Value!); internal static readonly string[] variants = Enum.GetNames<Tag>(); #endregion @@ -240,7 +240,52 @@ namespace SQLServer { return new(resTag.UnwrapErr()); } } - public static Result<any, Error> Deserialize(ref Deserializer des) { + public static Result<any, Error> De(ref Deserializer des) { + + var des2 = des; + var resByte = des2.DeserializeByte(); + + if (resByte.IsOK) { + var tag = (Tag)resByte.Unwrap(); + var resAny = tag switch { + Tag.NULL => new(NULL), + Tag.bigint => SQLServer.bigint.De(ref des2).Map(fn_bigint), + Tag.binary => SQLServer.binary.De(ref des2).Map(fn_binary), + Tag.bit => SQLServer.bit.De(ref des2).Map(fn_bit), + Tag.@char => SQLServer.@char.De(ref des2).Map(fn_char), + Tag.date => SQLServer.date.De(ref des2).Map(fn_date), + Tag.datetime => SQLServer.datetime.De(ref des2).Map(fn_datetime), + Tag.datetime2 => SQLServer.datetime2.De(ref des2).Map(fn_datetime2), + Tag.datetimeoffset => SQLServer.datetimeoffset.De(ref des2).Map(fn_datetimeoffset), + Tag.@decimal => SQLServer.@decimal.De(ref des2).Map(fn_decimal), + Tag.@float => SQLServer.@float.De(ref des2).Map(fn_float), + Tag.image => SQLServer.image.De(ref des2).Map(fn_image), + Tag.@int => SQLServer.@int.De(ref des2).Map(fn_int), + Tag.money => SQLServer.money.De(ref des2).Map(fn_money), + Tag.nchar => SQLServer.nchar.De(ref des2).Map(fn_nchar), + Tag.ntext => SQLServer.ntext.De(ref des2).Map(fn_ntext), + Tag.nvarchar => SQLServer.nvarchar.De(ref des2).Map(fn_nvarchar), + Tag.real => SQLServer.real.De(ref des2).Map(fn_real), + Tag.smalldatetime => SQLServer.smalldatetime.De(ref des2).Map(fn_smalldatetime), + Tag.smallint => SQLServer.smallint.De(ref des2).Map(fn_smallint), + Tag.smallmoney => SQLServer.smallmoney.De(ref des2).Map(fn_smallmoney), + Tag.sql_variant => SQLServer.sql_variant.De(ref des2).Map(fn_sql_variant), + Tag.text => SQLServer.text.De(ref des2).Map(fn_text), + Tag.time => SQLServer.time.De(ref des2).Map(fn_time), + Tag.tinyint => SQLServer.tinyint.De(ref des2).Map(fn_tinyint), + Tag.uniqueidentifier => SQLServer.uniqueidentifier.De(ref des2).Map(fn_uniqueidentifier), + Tag.varbinary => SQLServer.varbinary.De(ref des2).Map(fn_varbinary), + Tag.varchar => SQLServer.varchar.De(ref des2).Map(fn_varchar), + Tag.xml => SQLServer.xml.De(ref des2).Map(fn_xml), + _ => new(Error.UnknownVariant(tag.ToString(), variants)), + }; + if (resAny.IsOK) { des = des2; } + return resAny; + } else { + return new(resByte.UnwrapErr()); + } + } + public static Result<any, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { var des2 = des; var resByte = des2.DeserializeByte(); @@ -426,7 +471,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 16)] - public readonly struct bigint: IDataType, IInto<bigint> { + public readonly struct bigint: IDataType, IInto<bigint>, IBinDeserializable<bigint> { #region Type-level Constructors #endregion @@ -454,14 +499,26 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<long, Error> Deserialize(ref Deserializer des) { + public static Result<bigint, Error> De(ref Deserializer des) { var des2 = des; var resLong = des2.DeserializeLong(); if (resLong.IsOK) { des = des2; - return new(resLong.Unwrap()); + return new(new bigint(resLong.Unwrap())); + } else { + return new(resLong.UnwrapErr()); + } + } + public static Result<bigint, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resLong = des2.DeserializeLong(); + + if (resLong.IsOK) { + des = des2; + return new(new bigint(resLong.Unwrap())); } else { return new(resLong.UnwrapErr()); } @@ -508,7 +565,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 8)] - public readonly struct binary: IDataType, IInto<binary> { + public readonly struct binary: IDataType, IInto<binary>, IBinDeserializable<binary> { #region Type-level Constructors #endregion @@ -536,7 +593,7 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<byte[], Error> Deserialize(ref Deserializer des) { + public static Result<binary, Error> De(ref Deserializer des) { var des2 = des; var resUshort = des2.DeserializeUshort(); @@ -549,7 +606,7 @@ namespace SQLServer { if ((uint)bytes.Length == len) { des = des2; - return new(bytes.ToArray()); + return new(new binary(bytes.ToArray())); } else { return new(Error.InvalidLength((ulong)bytes.Length, (@ushort)len)); } @@ -560,6 +617,32 @@ namespace SQLServer { return new(resUshort.UnwrapErr()); } } + public static Result<binary, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resUshort = des2.DeserializeUshort(); + + if (resUshort.IsOK) { + var len = resUshort.Unwrap(); + + if (len is > ushort.MinValue and <= 8000) { + Span<byte> bytes = stackalloc byte[len]; + uint l; + des2.Deserialize(bytes); + + if ((l = des2.Deserialize(bytes)) == len) { + des = des2; + return new(new binary(bytes.ToArray())); + } else { + return new(Error.InvalidLength((ulong)l, (@ushort)len)); + } + } else { + return new(Error.InvalidLength(len, ushort1To8000)); + } + } else { + return new(resUshort.UnwrapErr()); + } + } public static Result<binary, OutOfRangeErr> New(byte[] val) => val.Length is 0 or > 8000 ? new(OutOfRangeErr.OutOfRange) : new(new binary(val)); public static Result<binary, OutOfRangeErr> New(ReadOnlySpan<byte> val) => val.Length is 0 or > 8000 ? new(OutOfRangeErr.OutOfRange) : new(new binary(val.ToArray())); #endregion @@ -605,7 +688,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 1, Size = 2)] - public readonly struct bit: IDataType, IInto<bit> { + public readonly struct bit: IDataType, IInto<bit>, IBinDeserializable<bit> { #region Type-level Constructors #endregion @@ -633,14 +716,26 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<bool, Error> Deserialize(ref Deserializer des) { + public static Result<bit, Error> De(ref Deserializer des) { var des2 = des; var resBool = des2.DeserializeBool(); if (resBool.IsOK) { des = des2; - return new(resBool.Unwrap()); + return new(new bit(resBool.Unwrap())); + } else { + return new(resBool.UnwrapErr()); + } + } + public static Result<bit, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resBool = des2.DeserializeBool(); + + if (resBool.IsOK) { + des = des2; + return new(new bit(resBool.Unwrap())); } else { return new(resBool.UnwrapErr()); } @@ -687,7 +782,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 8)] - public readonly struct @char: IDataType, IInto<@char>, ISerializable { + public readonly struct @char: IDataType, IInto<@char>, ISerializable, IBinDeserializable<@char> { #region Type-level Constructors #endregion @@ -715,7 +810,7 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<string, Error> Deserialize(ref Deserializer des) { + public static Result<@char, Error> De(ref Deserializer des) { var des2 = des; var resUshort = des2.DeserializeUshort(); @@ -728,7 +823,7 @@ namespace SQLServer { if ((uint)chars.Length == len) { des = des2; - return new(new string(chars)); + return new(new @char(new string(chars))); } else { return new(Error.InvalidLength((ulong)chars.Length, (@ushort)len)); } @@ -739,6 +834,31 @@ namespace SQLServer { return new(resUshort.UnwrapErr()); } } + public static Result<@char, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resUshort = des2.DeserializeUshort(); + + if (resUshort.IsOK) { + var len = resUshort.Unwrap(); + + if (len is > ushort.MinValue and <= 8000) { + uint l; + Span<char> chars = stackalloc char[len]; + + if ((l = des2.DeserializeChars(chars)) == len) { + des = des2; + return new(new @char(new string(chars))); + } else { + return new(Error.InvalidLength((ulong)l, (@ushort)len)); + } + } else { + return new(Error.InvalidLength(len, ushort1To8000)); + } + } else { + return new(resUshort.UnwrapErr()); + } + } public static Result<@char, OutOfRangeErr> New(string val) => val.Length is 0 or > 8000 ? new(OutOfRangeErr.OutOfRange) : new(new @char(val)); #endregion @@ -783,7 +903,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 8)] - public readonly struct date: IDataType, IInto<date> { + public readonly struct date: IDataType, IInto<date>, IBinDeserializable<date> { #region Type-level Constructors #endregion @@ -811,7 +931,7 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<System.DateTime, Error> Deserialize(ref Deserializer des) { + public static Result<date, Error> De(ref Deserializer des) { var des2 = des; var resDateTime = des2.DeserializeDateTime(); @@ -821,7 +941,25 @@ namespace SQLServer { if (date == date.Date) { des = des2; - return new(date); + return new(new date(date)); + } else { + return new(Error.InvalidValue(Unexpected.DateTime(date), validDate)); + } + } else { + return new(resDateTime.UnwrapErr()); + } + } + public static Result<date, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resDateTime = des2.DeserializeDateTime(); + + if (resDateTime.IsOK) { + var date = resDateTime.Unwrap(); + + if (date == date.Date) { + des = des2; + return new(new date(date)); } else { return new(Error.InvalidValue(Unexpected.DateTime(date), validDate)); } @@ -870,7 +1008,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 4, Size = 12)] - public readonly struct datetime: IDataType, IInto<datetime> { + public readonly struct datetime: IDataType, IInto<datetime>, IBinDeserializable<datetime> { #region Type-level Constructors #endregion @@ -898,7 +1036,25 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<SqlDateTime, Error> Deserialize(ref Deserializer des) { + public static Result<datetime, Error> De(ref Deserializer des) { + + var des2 = des; + var resDateTime = des2.DeserializeDateTime(); + + if (resDateTime.IsOK) { + var date = resDateTime.Unwrap(); + + if (date >= SqlDateTime.MinValue.Value && date <= SqlDateTime.MaxValue.Value && date == new SqlDateTime(date).Value) { + des = des2; + return new(new datetime(new SqlDateTime(date))); + } else { + return new(Error.InvalidValue(Unexpected.DateTime(date), validDatetime)); + } + } else { + return new(resDateTime.UnwrapErr()); + } + } + public static Result<datetime, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { var des2 = des; var resDateTime = des2.DeserializeDateTime(); @@ -908,7 +1064,7 @@ namespace SQLServer { if (date >= SqlDateTime.MinValue.Value && date <= SqlDateTime.MaxValue.Value && date == new SqlDateTime(date).Value) { des = des2; - return new(new SqlDateTime(date)); + return new(new datetime(new SqlDateTime(date))); } else { return new(Error.InvalidValue(Unexpected.DateTime(date), validDatetime)); } @@ -959,7 +1115,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 16)] - public readonly struct datetime2: IDataType, IInto<datetime2> { + public readonly struct datetime2: IDataType, IInto<datetime2>, IBinDeserializable<datetime2> { #region Type-level Constructors #endregion @@ -987,14 +1143,26 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<System.DateTime, Error> Deserialize(ref Deserializer des) { + public static Result<datetime2, Error> De(ref Deserializer des) { + + var des2 = des; + var resDateTime = des2.DeserializeDateTime(); + + if (resDateTime.IsOK) { + des = des2; + return new(new datetime2(resDateTime.Unwrap())); + } else { + return new(resDateTime.UnwrapErr()); + } + } + public static Result<datetime2, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { var des2 = des; var resDateTime = des2.DeserializeDateTime(); if (resDateTime.IsOK) { des = des2; - return new(resDateTime.Unwrap()); + return new(new datetime2(resDateTime.Unwrap())); } else { return new(resDateTime.UnwrapErr()); } @@ -1041,7 +1209,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 24)] - public readonly struct datetimeoffset: IDataType, IInto<datetimeoffset> { + public readonly struct datetimeoffset: IDataType, IInto<datetimeoffset>, IBinDeserializable<datetimeoffset> { #region Type-level Constructors #endregion @@ -1069,14 +1237,26 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<System.DateTimeOffset, Error> Deserialize(ref Deserializer des) { + public static Result<datetimeoffset, Error> De(ref Deserializer des) { var des2 = des; var resDateTimeOffset = des2.DeserializeDateTimeOffset(); if (resDateTimeOffset.IsOK) { des = des2; - return new(resDateTimeOffset.Unwrap()); + return new(new datetimeoffset(resDateTimeOffset.Unwrap())); + } else { + return new(resDateTimeOffset.UnwrapErr()); + } + } + public static Result<datetimeoffset, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resDateTimeOffset = des2.DeserializeDateTimeOffset(); + + if (resDateTimeOffset.IsOK) { + des = des2; + return new(new datetimeoffset(resDateTimeOffset.Unwrap())); } else { return new(resDateTimeOffset.UnwrapErr()); } @@ -1123,7 +1303,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 4, Size = 20)] - public readonly struct @decimal: IDataType, IInto<@decimal> { + public readonly struct @decimal: IDataType, IInto<@decimal>, IBinDeserializable<@decimal> { #region Type-level Constructors #endregion @@ -1153,7 +1333,7 @@ namespace SQLServer { #region Type-level Functions [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Need to since we shouldn't make assumptions about how SqlDecimal with throw an exception.")] - public static Result<SqlDecimal, Error> Deserialize(ref Deserializer des) { + public static Result<@decimal, Error> De(ref Deserializer des) { var des2 = des; var resByte = des2.DeserializeByte(); @@ -1173,7 +1353,50 @@ namespace SQLServer { try { var val = new SqlDecimal(prec, scale, resBool.Unwrap(), data[0], data[1], data[2], data[3]); des = des2; - return new(val); + return new(new @decimal(val)); + } catch (Exception) { + return new(Error.Custom(validSqlDecimal)); + } + } else { + return new(Error.InvalidLength((ulong)data.Length, fourInts)); + } + } else { + return new(resBool.UnwrapErr()); + } + } else { + return new(resByte.UnwrapErr()); + } + } else { + return new(resByte.UnwrapErr()); + } + } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Need to since we shouldn't make assumptions about how SqlDecimal with throw an exception.")] + public static Result<@decimal, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resByte = des2.DeserializeByte(); + + if (resByte.IsOK) { + var prec = resByte.Unwrap(); + resByte = des2.DeserializeByte(); + + if (resByte.IsOK) { + var scale = resByte.Unwrap(); + var resBool = des2.DeserializeBool(); + + if (resBool.IsOK) { + Span<byte> data = stackalloc byte[16]; + + if (des2.Deserialize(data) == 4) { + try { + unsafe { + fixed (byte* ptr = data) { + var ptr2 = (int*)ptr; + var val = new SqlDecimal(prec, scale, resBool.Unwrap(), *ptr2++, *ptr2++, *ptr2++, *ptr2); + des = des2; + return new(new @decimal(val)); + } + } } catch (Exception) { return new(Error.Custom(validSqlDecimal)); } @@ -1418,7 +1641,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 8)] - public readonly struct @float: IDataType, IInto<@float> { + public readonly struct @float: IDataType, IInto<@float>, IBinDeserializable<@float> { #region Type-level Constructors #endregion @@ -1446,7 +1669,7 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<double, Error> Deserialize(ref Deserializer des) { + public static Result<@float, Error> De(ref Deserializer des) { var des2 = des; var resDouble = des2.DeserializeDouble(); @@ -1456,7 +1679,25 @@ namespace SQLServer { if (double.IsFinite(val)) { des = des2; - return new(val); + return new(new @float(val)); + } else { + return new(Error.InvalidValue(Unexpected.Double(val), finiteDouble)); + } + } else { + return new(resDouble.UnwrapErr()); + } + } + public static Result<@float, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resDouble = des2.DeserializeDouble(); + + if (resDouble.IsOK) { + var val = resDouble.Unwrap(); + + if (double.IsFinite(val)) { + des = des2; + return new(new @float(val)); } else { return new(Error.InvalidValue(Unexpected.Double(val), finiteDouble)); } @@ -1505,7 +1746,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 8)] - public readonly struct image: IDataType, IInto<image> { + public readonly struct image: IDataType, IInto<image>, IBinDeserializable<image> { #region Type-level Constructors #endregion @@ -1532,7 +1773,7 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<byte[], Error> Deserialize(ref Deserializer des) { + public static Result<image, Error> De(ref Deserializer des) { var des2 = des; var resUint = des2.DeserializeUint(); @@ -1543,7 +1784,7 @@ namespace SQLServer { if ((uint)bytes.Length == len) { des = des2; - return new(bytes.ToArray()); + return new(new image(bytes.ToArray())); } else { return new(Error.InvalidLength((ulong)bytes.Length, (@uint)len)); } @@ -1551,6 +1792,26 @@ namespace SQLServer { return new(resUint.UnwrapErr()); } } + public static Result<image, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resUint = des2.DeserializeUint(); + + if (resUint.IsOK) { + var len = resUint.Unwrap(); + uint l; + var bytes = new byte[len]; + + if ((l = des2.Deserialize(bytes.AsSpan())) == len) { + des = des2; + return new(new image(bytes)); + } else { + return new(Error.InvalidLength((ulong)l, (@uint)len)); + } + } else { + return new(resUint.UnwrapErr()); + } + } public static image New(byte[] val) => new(val); public static image New(ReadOnlySpan<byte> val) => new(val.ToArray()); #endregion @@ -1596,7 +1857,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 4, Size = 8)] - public readonly struct @int: IDataType, IInto<@int> { + public readonly struct @int: IDataType, IInto<@int>, IBinDeserializable<@int> { #region Type-level Constructors #endregion @@ -1624,14 +1885,26 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<int, Error> Deserialize(ref Deserializer des) { + public static Result<@int, Error> De(ref Deserializer des) { var des2 = des; var resInt = des2.DeserializeInt(); if (resInt.IsOK) { des = des2; - return new(resInt.Unwrap()); + return new(new @int(resInt.Unwrap())); + } else { + return new(resInt.UnwrapErr()); + } + } + public static Result<@int, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resInt = des2.DeserializeInt(); + + if (resInt.IsOK) { + des = des2; + return new(new @int(resInt.Unwrap())); } else { return new(resInt.UnwrapErr()); } @@ -1678,7 +1951,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 16)] - public readonly struct money: IDataType, IInto<money> { + public readonly struct money: IDataType, IInto<money>, IBinDeserializable<money> { #region Type-level Constructors #endregion @@ -1706,7 +1979,25 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<SqlMoney, Error> Deserialize(ref Deserializer des) { + public static Result<money, Error> De(ref Deserializer des) { + + var des2 = des; + var resDecimal = des2.DeserializeDecimal(); + + if (resDecimal.IsOK) { + var dec = resDecimal.Unwrap(); + + if (dec >= SqlMoney.MinValue.Value && dec <= SqlMoney.MaxValue.Value && dec == new SqlMoney(dec).Value) { + des = des2; + return new(new money(new SqlMoney(dec))); + } else { + return new(Error.InvalidValue(Unexpected.Decimal(dec), validMoney)); + } + } else { + return new(resDecimal.UnwrapErr()); + } + } + public static Result<money, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { var des2 = des; var resDecimal = des2.DeserializeDecimal(); @@ -1716,7 +2007,7 @@ namespace SQLServer { if (dec >= SqlMoney.MinValue.Value && dec <= SqlMoney.MaxValue.Value && dec == new SqlMoney(dec).Value) { des = des2; - return new(new SqlMoney(dec)); + return new(new money(new SqlMoney(dec))); } else { return new(Error.InvalidValue(Unexpected.Decimal(dec), validMoney)); } @@ -1767,7 +2058,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 8)] - public readonly struct nchar: IDataType, IInto<nchar> { + public readonly struct nchar: IDataType, IInto<nchar>, IBinDeserializable<nchar> { #region Type-level Constructors #endregion @@ -1795,7 +2086,7 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<string, Error> Deserialize(ref Deserializer des) { + public static Result<nchar, Error> De(ref Deserializer des) { var des2 = des; var resUshort = des2.DeserializeUshort(); @@ -1808,7 +2099,7 @@ namespace SQLServer { if ((uint)chars.Length == len) { des = des2; - return new(new string(chars)); + return new(new nchar(new string(chars))); } else { return new(Error.InvalidLength((ulong)chars.Length, (@ushort)len)); } @@ -1819,6 +2110,31 @@ namespace SQLServer { return new(resUshort.UnwrapErr()); } } + public static Result<nchar, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resUshort = des2.DeserializeUshort(); + + if (resUshort.IsOK) { + var len = resUshort.Unwrap(); + + if (len is > ushort.MinValue and <= 4000) { + uint l; + Span<char> chars = stackalloc char[len]; + + if ((l = des2.DeserializeChars(chars)) == len) { + des = des2; + return new(new nchar(new string(chars))); + } else { + return new(Error.InvalidLength((ulong)l, (@ushort)len)); + } + } else { + return new(Error.InvalidLength(len, ushort1To4000)); + } + } else { + return new(resUshort.UnwrapErr()); + } + } public static Result<nchar, OutOfRangeErr> New(string val) => val.Length is 0 or > 4000 ? new(OutOfRangeErr.OutOfRange) : new(new nchar(val)); #endregion @@ -1863,7 +2179,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 8)] - public readonly struct ntext: IDataType, IInto<ntext> { + public readonly struct ntext: IDataType, IInto<ntext>, IBinDeserializable<ntext> { #region Type-level Constructors #endregion @@ -1890,7 +2206,7 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<string, Error> Deserialize(ref Deserializer des) { + public static Result<ntext, Error> De(ref Deserializer des) { var des2 = des; var resUint = des2.DeserializeUint(); @@ -1901,7 +2217,7 @@ namespace SQLServer { if ((uint)chars.Length == len) { des = des2; - return new(new string(chars)); + return new(new ntext(new string(chars))); } else { return new(Error.InvalidLength((ulong)chars.Length, (@uint)len)); } @@ -1909,6 +2225,26 @@ namespace SQLServer { return new(resUint.UnwrapErr()); } } + public static Result<ntext, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resUint = des2.DeserializeUint(); + + if (resUint.IsOK) { + var len = resUint.Unwrap(); + uint l; + var chars = new char[len]; + + if ((l = des2.DeserializeChars(chars)) == len) { + des = des2; + return new(new ntext(new string(chars))); + } else { + return new(Error.InvalidLength((ulong)l, (@uint)len)); + } + } else { + return new(resUint.UnwrapErr()); + } + } public static ntext New(string val) => new(val); #endregion @@ -1954,7 +2290,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 8)] - public readonly struct nvarchar: IDataType, IInto<nvarchar> { + public readonly struct nvarchar: IDataType, IInto<nvarchar>, IBinDeserializable<nvarchar> { #region Type-level Constructors #endregion @@ -1981,7 +2317,7 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<string, Error> Deserialize(ref Deserializer des) { + public static Result<nvarchar, Error> De(ref Deserializer des) { var des2 = des; var resUint = des2.DeserializeUint(); @@ -1992,7 +2328,7 @@ namespace SQLServer { if ((uint)chars.Length == len) { des = des2; - return new(new string(chars)); + return new(new nvarchar(new string(chars))); } else { return new(Error.InvalidLength((ulong)chars.Length, (@uint)len)); } @@ -2000,6 +2336,26 @@ namespace SQLServer { return new(resUint.UnwrapErr()); } } + public static Result<nvarchar, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resUint = des2.DeserializeUint(); + + if (resUint.IsOK) { + var len = resUint.Unwrap(); + uint l; + var chars = new char[len]; + + if ((l = des2.DeserializeChars(chars)) == len) { + des = des2; + return new(new nvarchar(new string(chars))); + } else { + return new(Error.InvalidLength((ulong)l, (@uint)len)); + } + } else { + return new(resUint.UnwrapErr()); + } + } public static nvarchar New(string val) => new(val); #endregion @@ -2045,7 +2401,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 4, Size = 4)] - public readonly struct real: IDataType, IInto<real> { + public readonly struct real: IDataType, IInto<real>, IBinDeserializable<real> { #region Type-level Constructors #endregion @@ -2073,7 +2429,7 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<float, Error> Deserialize(ref Deserializer des) { + public static Result<real, Error> De(ref Deserializer des) { var des2 = des; var resFloat = des2.DeserializeFloat(); @@ -2083,7 +2439,25 @@ namespace SQLServer { if (float.IsFinite(val)) { des = des2; - return new(val); + return new(new real(val)); + } else { + return new(Error.InvalidValue(Unexpected.Float(val), finiteFloat)); + } + } else { + return new(resFloat.UnwrapErr()); + } + } + public static Result<real, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resFloat = des2.DeserializeFloat(); + + if (resFloat.IsOK) { + var val = resFloat.Unwrap(); + + if (float.IsFinite(val)) { + des = des2; + return new(new real(val)); } else { return new(Error.InvalidValue(Unexpected.Float(val), finiteFloat)); } @@ -2132,7 +2506,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 4, Size = 12)] - public readonly struct smalldatetime: IDataType, IInto<smalldatetime> { + public readonly struct smalldatetime: IDataType, IInto<smalldatetime>, IBinDeserializable<smalldatetime> { #region Type-level Constructors #endregion @@ -2166,7 +2540,7 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<SqlDateTime, Error> Deserialize(ref Deserializer des) { + public static Result<smalldatetime, Error> De(ref Deserializer des) { var des2 = des; var resDateTime = des2.DeserializeDateTime(); @@ -2176,7 +2550,25 @@ namespace SQLServer { if (date >= Min.Value && date <= Max.Value && date.Ticks == (date.Date.Ticks + (date.Hour * System.TimeSpan.TicksPerHour) + (date.Minute * System.TimeSpan.TicksPerMinute)) && date == new SqlDateTime(date).Value) { des = des2; - return new(new SqlDateTime(date)); + return new(new smalldatetime(new SqlDateTime(date))); + } else { + return new(Error.InvalidValue(Unexpected.DateTime(date), validSmalldatetime)); + } + } else { + return new(resDateTime.UnwrapErr()); + } + } + public static Result<smalldatetime, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resDateTime = des2.DeserializeDateTime(); + + if (resDateTime.IsOK) { + var date = resDateTime.Unwrap(); + + if (date >= Min.Value && date <= Max.Value && date.Ticks == (date.Date.Ticks + (date.Hour * System.TimeSpan.TicksPerHour) + (date.Minute * System.TimeSpan.TicksPerMinute)) && date == new SqlDateTime(date).Value) { + des = des2; + return new(new smalldatetime(new SqlDateTime(date))); } else { return new(Error.InvalidValue(Unexpected.DateTime(date), validSmalldatetime)); } @@ -2232,7 +2624,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 2, Size = 4)] - public readonly struct smallint: IDataType, IInto<smallint> { + public readonly struct smallint: IDataType, IInto<smallint>, IBinDeserializable<smallint> { #region Type-level Constructors #endregion @@ -2260,14 +2652,26 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<short, Error> Deserialize(ref Deserializer des) { + public static Result<smallint, Error> De(ref Deserializer des) { var des2 = des; var resShort = des2.DeserializeShort(); if (resShort.IsOK) { des = des2; - return new(resShort.Unwrap()); + return new(new smallint(resShort.Unwrap())); + } else { + return new(resShort.UnwrapErr()); + } + } + public static Result<smallint, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resShort = des2.DeserializeShort(); + + if (resShort.IsOK) { + des = des2; + return new(new smallint(resShort.Unwrap())); } else { return new(resShort.UnwrapErr()); } @@ -2314,7 +2718,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 16)] - public readonly struct smallmoney: IDataType, IInto<smallmoney> { + public readonly struct smallmoney: IDataType, IInto<smallmoney>, IBinDeserializable<smallmoney> { #region Type-level Constructors #endregion @@ -2344,7 +2748,25 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<SqlMoney, Error> Deserialize(ref Deserializer des) { + public static Result<smallmoney, Error> De(ref Deserializer des) { + + var des2 = des; + var resDecimal = des2.DeserializeDecimal(); + + if (resDecimal.IsOK) { + var dec = resDecimal.Unwrap(); + + if (dec >= Min.Value && dec <= Max.Value && dec == new SqlMoney(dec).Value) { + des = des2; + return new(new smallmoney(new SqlMoney(dec))); + } else { + return new(Error.InvalidValue(Unexpected.Decimal(dec), validSmallmoney)); + } + } else { + return new(resDecimal.UnwrapErr()); + } + } + public static Result<smallmoney, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { var des2 = des; var resDecimal = des2.DeserializeDecimal(); @@ -2354,7 +2776,7 @@ namespace SQLServer { if (dec >= Min.Value && dec <= Max.Value && dec == new SqlMoney(dec).Value) { des = des2; - return new(new SqlMoney(dec)); + return new(new smallmoney(new SqlMoney(dec))); } else { return new(Error.InvalidValue(Unexpected.Decimal(dec), validSmallmoney)); } @@ -2404,7 +2826,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 32)] - public readonly struct sql_variant: ISum<Unit, long, byte[], bool, string, System.DateTime, SqlDateTime, System.DateTime, System.DateTimeOffset, SqlDecimal, double, int, SqlMoney, string, string, float, SqlDateTime, short, SqlMoney, System.TimeSpan, byte, System.Guid, byte[], string>, IDataType, IInto<sql_variant> { + public readonly struct sql_variant: ISum<Unit, long, byte[], bool, string, System.DateTime, SqlDateTime, System.DateTime, System.DateTimeOffset, SqlDecimal, double, int, SqlMoney, string, string, float, SqlDateTime, short, SqlMoney, System.TimeSpan, byte, System.Guid, byte[], string>, IDataType, IInto<sql_variant>, IBinDeserializable<sql_variant> { #region Type-level Constructors #endregion @@ -2432,29 +2854,29 @@ namespace SQLServer { #region Type-level Fields static readonly @string ZeroTo4000= "0–4000"; static readonly @string ZeroTo8000 = "0–8000"; - static readonly Fn<long, sql_variant> fn_bigint = (x) => new(x); - static readonly Fn<byte[], sql_variant> fn_binary = (x) => new(Tag.binary, x); - static readonly Fn<bool, sql_variant> fn_bit = (x) => new(x); - static readonly Fn<string, sql_variant> fn_char = (x) => new(Tag.@char, x); - static readonly Fn<System.DateTime, sql_variant> fn_date = (x) => new(x); - static readonly Fn<SqlDateTime, sql_variant> fn_datetime = (x) => new(Tag.datetime, x); - static readonly Fn<System.DateTime, sql_variant> fn_datetime2 = (x) => new(x); - static readonly Fn<System.DateTimeOffset, sql_variant> fn_datetimeoffset = (x) => new(x); - static readonly Fn<SqlDecimal, sql_variant> fn_decimal = (x) => new(x); - static readonly Fn<double, sql_variant> fn_float = (x) => new(x); - static readonly Fn<int, sql_variant> fn_int = (x) => new(x); - static readonly Fn<SqlMoney, sql_variant> fn_money = (x) => new(Tag.money, x); - static readonly Fn<string, sql_variant> fn_nchar = (x) => new(Tag.nchar, x); - static readonly Fn<string, Result<sql_variant, Error>> fn_nvarchar = (x) => x.Length > 4000 ? new(Error.InvalidLength((ulong)x.Length, ZeroTo4000)) : new(new sql_variant(Tag.nvarchar, x)); - static readonly Fn<float, sql_variant> fn_real = (x) => new(x); - static readonly Fn<SqlDateTime, sql_variant> fn_smalldatetime = (x) => new(Tag.smalldatetime, x); - static readonly Fn<short, sql_variant> fn_smallint = (x) => new(x); - static readonly Fn<SqlMoney, sql_variant> fn_smallmoney = (x) => new(Tag.smallmoney, x); - static readonly Fn<System.TimeSpan, sql_variant> fn_time = (x) => new(x); - static readonly Fn<byte, sql_variant> fn_tinyint = (x) => new(x); - static readonly Fn<System.Guid, sql_variant> fn_uniqueidentifier = (x) => new(x); - static readonly Fn<byte[], Result<sql_variant, Error>> fn_varbinary = (x) => x.Length > 8000 ? new(Error.InvalidLength((ulong)x.Length, ZeroTo8000)) : new(new sql_variant(Tag.varbinary, x)); - static readonly Fn<string, Result<sql_variant, Error>> fn_varchar = (x) => x.Length > 8000 ? new(Error.InvalidLength((ulong)x.Length, ZeroTo8000)) : new(new sql_variant(Tag.varchar, x)); + static readonly Fn<bigint, sql_variant> fn_bigint = (x) => new(x.Value); + static readonly Fn<binary, sql_variant> fn_binary = (x) => new(Tag.binary, x.Value!); + static readonly Fn<bit, sql_variant> fn_bit = (x) => new(x.Value); + static readonly Fn<@char, sql_variant> fn_char = (x) => new(Tag.@char, x.Value!); + static readonly Fn<date, sql_variant> fn_date = (x) => new(x.Value); + static readonly Fn<datetime, sql_variant> fn_datetime = (x) => new(Tag.datetime, x.Value); + static readonly Fn<datetime2, sql_variant> fn_datetime2 = (x) => new(x.Value); + static readonly Fn<datetimeoffset, sql_variant> fn_datetimeoffset = (x) => new(x.Value); + static readonly Fn<@decimal, sql_variant> fn_decimal = (x) => new(x.Value); + static readonly Fn<@float, sql_variant> fn_float = (x) => new(x.Value); + static readonly Fn<@int, sql_variant> fn_int = (x) => new(x.Value); + static readonly Fn<money, sql_variant> fn_money = (x) => new(Tag.money, x.Value); + static readonly Fn<nchar, sql_variant> fn_nchar = (x) => new(Tag.nchar, x.Value!); + static readonly Fn<nvarchar, Result<sql_variant, Error>> fn_nvarchar = (x) => x.Value!.Length > 4000 ? new(Error.InvalidLength((ulong)x.Value.Length, ZeroTo4000)) : new(new sql_variant(Tag.nvarchar, x.Value)); + static readonly Fn<real, sql_variant> fn_real = (x) => new(x.Value); + static readonly Fn<smalldatetime, sql_variant> fn_smalldatetime = (x) => new(Tag.smalldatetime, x.Value); + static readonly Fn<smallint, sql_variant> fn_smallint = (x) => new(x.Value); + static readonly Fn<smallmoney, sql_variant> fn_smallmoney = (x) => new(Tag.smallmoney, x.Value); + static readonly Fn<time, sql_variant> fn_time = (x) => new(x.Value); + static readonly Fn<tinyint, sql_variant> fn_tinyint = (x) => new(x.Value); + static readonly Fn<uniqueidentifier, sql_variant> fn_uniqueidentifier = (x) => new(x.Value); + static readonly Fn<varbinary, Result<sql_variant, Error>> fn_varbinary = (x) => x.Value!.Length > 8000 ? new(Error.InvalidLength((ulong)x.Value.Length, ZeroTo8000)) : new(new sql_variant(Tag.varbinary, x.Value)); + static readonly Fn<varchar, Result<sql_variant, Error>> fn_varchar = (x) => x.Value!.Length > 8000 ? new(Error.InvalidLength((ulong)x.Value.Length, ZeroTo8000)) : new(new sql_variant(Tag.varchar, x.Value)); static readonly string[] variants = Enum.GetNames<Tag>(); public static readonly sql_variant NULL = new(); #endregion @@ -2572,7 +2994,47 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<sql_variant, Error> Deserialize(ref Deserializer des) { + public static Result<sql_variant, Error> De(ref Deserializer des) { + + var des2 = des; + var resByte = des2.DeserializeByte(); + + if (resByte.IsOK) { + var tag = (Tag)resByte.Unwrap(); + var resSql_variant = tag switch { + Tag.NULL => new(NULL), + Tag.bigint => SQLServer.bigint.De(ref des2).Map(fn_bigint), + Tag.binary => SQLServer.binary.De(ref des2).Map(fn_binary), + Tag.bit => SQLServer.bit.De(ref des2).Map(fn_bit), + Tag.@char => SQLServer.@char.De(ref des2).Map(fn_char), + Tag.date => SQLServer.date.De(ref des2).Map(fn_date), + Tag.datetime => SQLServer.datetime.De(ref des2).Map(fn_datetime), + Tag.datetime2 => SQLServer.datetime2.De(ref des2).Map(fn_datetime2), + Tag.datetimeoffset => SQLServer.datetimeoffset.De(ref des2).Map(fn_datetimeoffset), + Tag.@decimal => SQLServer.@decimal.De(ref des2).Map(fn_decimal), + Tag.@float => SQLServer.@float.De(ref des2).Map(fn_float), + Tag.@int => SQLServer.@int.De(ref des2).Map(fn_int), + Tag.money => SQLServer.money.De(ref des2).Map(fn_money), + Tag.nchar => SQLServer.nchar.De(ref des2).Map(fn_nchar), + Tag.nvarchar => SQLServer.nvarchar.De(ref des2).AndThen(fn_nvarchar), + Tag.real => SQLServer.real.De(ref des2).Map(fn_real), + Tag.smalldatetime => SQLServer.smalldatetime.De(ref des2).Map(fn_smalldatetime), + Tag.smallint => SQLServer.smallint.De(ref des2).Map(fn_smallint), + Tag.smallmoney => SQLServer.smallmoney.De(ref des2).Map(fn_smallmoney), + Tag.time => SQLServer.time.De(ref des2).Map(fn_time), + Tag.tinyint => SQLServer.tinyint.De(ref des2).Map(fn_tinyint), + Tag.uniqueidentifier => SQLServer.uniqueidentifier.De(ref des2).Map(fn_uniqueidentifier), + Tag.varbinary => SQLServer.varbinary.De(ref des2).AndThen(fn_varbinary), + Tag.varchar => SQLServer.varchar.De(ref des2).AndThen(fn_varchar), + _ => new(Error.UnknownVariant(tag.ToString(), variants)), + }; + if (resSql_variant.IsOK) { des = des2; } + return resSql_variant; + } else { + return new(resByte.UnwrapErr()); + } + } + public static Result<sql_variant, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { var des2 = des; var resByte = des2.DeserializeByte(); @@ -2805,7 +3267,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 8)] - public readonly struct text: IDataType, IInto<text> { + public readonly struct text: IDataType, IInto<text>, IBinDeserializable<text> { #region Type-level Constructors #endregion @@ -2832,7 +3294,7 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<string, Error> Deserialize(ref Deserializer des) { + public static Result<text, Error> De(ref Deserializer des) { var des2 = des; var resUint = des2.DeserializeUint(); @@ -2843,7 +3305,7 @@ namespace SQLServer { if ((uint)chars.Length == len) { des = des2; - return new(new string(chars)); + return new(new text(new string(chars))); } else { return new(Error.InvalidLength((ulong)chars.Length, (@uint)len)); } @@ -2851,6 +3313,26 @@ namespace SQLServer { return new(resUint.UnwrapErr()); } } + public static Result<text, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resUint = des2.DeserializeUint(); + + if (resUint.IsOK) { + var len = resUint.Unwrap(); + uint l; + var chars = new char[len]; + + if ((l = des2.DeserializeChars(chars)) == len) { + des = des2; + return new(new text(new string(chars))); + } else { + return new(Error.InvalidLength((ulong)l, (@uint)len)); + } + } else { + return new(resUint.UnwrapErr()); + } + } public static text New(string val) => new(val); #endregion @@ -2896,7 +3378,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 8)] - public readonly struct time: IDataType, IInto<time> { + public readonly struct time: IDataType, IInto<time>, IBinDeserializable<time> { #region Type-level Constructors #endregion @@ -2924,7 +3406,7 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<System.TimeSpan, Error> Deserialize(ref Deserializer des) { + public static Result<time, Error> De(ref Deserializer des) { var des2 = des; var resTimeSpan = des2.DeserializeTimeSpan(); @@ -2934,7 +3416,25 @@ namespace SQLServer { if (time >= System.TimeSpan.Zero && time < new System.TimeSpan(System.TimeSpan.TicksPerDay)) { des = des2; - return new(time); + return new(new time(time)); + } else { + return new(Error.InvalidValue(Unexpected.TimeSpan(time), validTime)); + } + } else { + return new(resTimeSpan.UnwrapErr()); + } + } + public static Result<time, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resTimeSpan = des2.DeserializeTimeSpan(); + + if (resTimeSpan.IsOK) { + var time = resTimeSpan.Unwrap(); + + if (time >= System.TimeSpan.Zero && time < new System.TimeSpan(System.TimeSpan.TicksPerDay)) { + des = des2; + return new(new time(time)); } else { return new(Error.InvalidValue(Unexpected.TimeSpan(time), validTime)); } @@ -2983,7 +3483,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 1, Size = 2)] - public readonly struct tinyint: IDataType, IInto<tinyint> { + public readonly struct tinyint: IDataType, IInto<tinyint>, IBinDeserializable<tinyint> { #region Type-level Constructors #endregion @@ -3011,14 +3511,26 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<byte, Error> Deserialize(ref Deserializer des) { + public static Result<tinyint, Error> De(ref Deserializer des) { var des2 = des; var resByte = des2.DeserializeByte(); if (resByte.IsOK) { des = des2; - return new(resByte.Unwrap()); + return new(new tinyint(resByte.Unwrap())); + } else { + return new(resByte.UnwrapErr()); + } + } + public static Result<tinyint, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resByte = des2.DeserializeByte(); + + if (resByte.IsOK) { + des = des2; + return new(new tinyint(resByte.Unwrap())); } else { return new(resByte.UnwrapErr()); } @@ -3065,7 +3577,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 4, Size = 20)] - public readonly struct uniqueidentifier: IDataType, IInto<uniqueidentifier> { + public readonly struct uniqueidentifier: IDataType, IInto<uniqueidentifier>, IBinDeserializable<uniqueidentifier> { #region Type-level Constructors #endregion @@ -3093,14 +3605,26 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<System.Guid, Error> Deserialize(ref Deserializer des) { + public static Result<uniqueidentifier, Error> De(ref Deserializer des) { + + var des2 = des; + var resGuid = des2.DeserializeGuid(); + + if (resGuid.IsOK) { + des = des2; + return new(new uniqueidentifier(resGuid.Unwrap())); + } else { + return new(resGuid.UnwrapErr()); + } + } + public static Result<uniqueidentifier, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { var des2 = des; var resGuid = des2.DeserializeGuid(); if (resGuid.IsOK) { des = des2; - return new(resGuid.Unwrap()); + return new(new uniqueidentifier(resGuid.Unwrap())); } else { return new(resGuid.UnwrapErr()); } @@ -3147,7 +3671,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 8)] - public readonly struct varbinary: IDataType, IInto<varbinary> { + public readonly struct varbinary: IDataType, IInto<varbinary>, IBinDeserializable<varbinary> { #region Type-level Constructors #endregion @@ -3174,7 +3698,7 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<byte[], Error> Deserialize(ref Deserializer des) { + public static Result<varbinary, Error> De(ref Deserializer des) { var des2 = des; var resUint = des2.DeserializeUint(); @@ -3185,7 +3709,7 @@ namespace SQLServer { if ((uint)bytes.Length == len) { des = des2; - return new(bytes.ToArray()); + return new(new varbinary(bytes.ToArray())); } else { return new(Error.InvalidLength((ulong)bytes.Length, (@uint)len)); } @@ -3193,6 +3717,26 @@ namespace SQLServer { return new(resUint.UnwrapErr()); } } + public static Result<varbinary, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resUint = des2.DeserializeUint(); + + if (resUint.IsOK) { + var len = resUint.Unwrap(); + uint l; + var bytes = new byte[len]; + + if ((l = des2.Deserialize(bytes)) == len) { + des = des2; + return new(new varbinary(bytes)); + } else { + return new(Error.InvalidLength((ulong)l, (@uint)len)); + } + } else { + return new(resUint.UnwrapErr()); + } + } public static varbinary New(byte[] val) => new(val); public static varbinary New(ReadOnlySpan<byte> val) => new(val.ToArray()); #endregion @@ -3238,7 +3782,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 8)] - public readonly struct varchar: IDataType, IInto<varchar> { + public readonly struct varchar: IDataType, IInto<varchar>, IBinDeserializable<varchar> { #region Type-level Constructors #endregion @@ -3265,7 +3809,7 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<string, Error> Deserialize(ref Deserializer des) { + public static Result<varchar, Error> De(ref Deserializer des) { var des2 = des; var resUint = des2.DeserializeUint(); @@ -3276,7 +3820,7 @@ namespace SQLServer { if ((uint)chars.Length == len) { des = des2; - return new(new string(chars)); + return new(new varchar(new string(chars))); } else { return new(Error.InvalidLength((ulong)chars.Length, (@uint)len)); } @@ -3284,6 +3828,26 @@ namespace SQLServer { return new(resUint.UnwrapErr()); } } + public static Result<varchar, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resUint = des2.DeserializeUint(); + + if (resUint.IsOK) { + var len = resUint.Unwrap(); + uint l; + var chars = new char[len]; + + if ((l = des2.DeserializeChars(chars)) == len) { + des = des2; + return new(new varchar(new string(chars))); + } else { + return new(Error.InvalidLength((ulong)l, (@uint)len)); + } + } else { + return new(resUint.UnwrapErr()); + } + } public static varchar New(string val) => new(val); #endregion @@ -3329,7 +3893,7 @@ namespace SQLServer { #endregion } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 8)] - public readonly struct xml: IDataType, IInto<xml> { + public readonly struct xml: IDataType, IInto<xml>, IBinDeserializable<xml> { #region Type-level Constructors #endregion @@ -3356,7 +3920,7 @@ namespace SQLServer { #endregion #region Type-level Functions - public static Result<string, Error> Deserialize(ref Deserializer des) { + public static Result<xml, Error> De(ref Deserializer des) { var des2 = des; var resUint = des2.DeserializeUint(); @@ -3367,7 +3931,7 @@ namespace SQLServer { if ((uint)chars.Length == len) { des = des2; - return new(new string(chars)); + return new(new xml(new string(chars))); } else { return new(Error.InvalidLength((ulong)chars.Length, (@uint)len)); } @@ -3375,6 +3939,26 @@ namespace SQLServer { return new(resUint.UnwrapErr()); } } + public static Result<xml, Error> Deserialize<TDes>(ref TDes des) where TDes: notnull, IDeserializer { + + var des2 = des; + var resUint = des2.DeserializeUint(); + + if (resUint.IsOK) { + var len = resUint.Unwrap(); + uint l; + var chars = new char[len]; + + if ((l = des2.DeserializeChars(chars)) == len) { + des = des2; + return new(new xml(new string(chars))); + } else { + return new(Error.InvalidLength((ulong)l, (@uint)len)); + } + } else { + return new(resUint.UnwrapErr()); + } + } public static xml New(string val) => new(val); #endregion @@ -3526,7 +4110,7 @@ namespace SQLServer { } else if (_err.IsSome) { return new(new(_err.Unwrap())); } else { - var resAny = any.Deserialize(ref _des); + var resAny = any.De(ref _des); if (resAny.IsOK) { _index++;