Skip to content

Commit

Permalink
Bug fix parsing a field as long does not work #172.
Browse files Browse the repository at this point in the history
  • Loading branch information
cleftheris committed Oct 7, 2020
1 parent d282d12 commit 8899926
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 18 deletions.
35 changes: 35 additions & 0 deletions src/indice.Edi/EdiReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,12 @@ private EdiContainerType Peek() {
/// <returns>A <see cref="Nullable{Int32}"/>. This method will return <c>null</c> at the end of an array.</returns>
public abstract int? ReadAsInt32();

/// <summary>
/// Reads the next EDI token from the stream as a <see cref="Nullable{Int64}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Int64}"/>. This method will return <c>null</c> at the end of an array.</returns>
public abstract long? ReadAsInt64();

/// <summary>
/// Reads the next EDI token from the stream as a <see cref="String"/>.
/// </summary>
Expand Down Expand Up @@ -432,6 +438,35 @@ internal virtual bool ReadInternal() {
throw EdiReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
}

internal long? ReadAsInt64Internal() {
EdiToken t;
if (!ReadInternal()) {
SetToken(EdiToken.None);
return null;
} else {
t = TokenType;
}
if (t == EdiToken.Null)
return null;
long i;
if (t == EdiToken.String) {
string s = (string)Value;
if (s != null) {
s = s.TrimStart('Z'); // Z suppresses leading zeros
}
if (string.IsNullOrEmpty(s)) {
SetToken(EdiToken.Null);
return null;
}
if (long.TryParse(s, NumberStyles.Integer, Culture, out i)) {
SetToken(EdiToken.Integer, i, false);
return i;
}
throw EdiReaderException.Create(this, "Could not convert string to Int64: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
}
throw EdiReaderException.Create(this, "Error reading Int64. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
}

internal string ReadAsStringInternal() {
EdiToken t;
if (!ReadInternal()) {
Expand Down
35 changes: 27 additions & 8 deletions src/indice.Edi/EdiSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,10 @@ internal void PopulateValue(EdiReader reader, Stack<EdiStructure> stack, ref Edi
case PrimitiveTypeCode.BooleanNullable:
PopulateBooleanValue(reader, structure, descriptor, useTheReader);
break;
case PrimitiveTypeCode.Byte: break;
case PrimitiveTypeCode.ByteNullable: break;
case PrimitiveTypeCode.UInt32: break;
case PrimitiveTypeCode.UInt32Nullable: break;
case PrimitiveTypeCode.SByte: break;
case PrimitiveTypeCode.SByteNullable: break;
case PrimitiveTypeCode.Int16: break;
Expand All @@ -234,14 +238,12 @@ internal void PopulateValue(EdiReader reader, Stack<EdiStructure> stack, ref Edi
case PrimitiveTypeCode.Int32Nullable:
PopulateInt32Value(reader, structure, descriptor, useTheReader);
break;
case PrimitiveTypeCode.Byte: break;
case PrimitiveTypeCode.ByteNullable: break;
case PrimitiveTypeCode.UInt32: break;
case PrimitiveTypeCode.UInt32Nullable: break;
case PrimitiveTypeCode.Int64: break;
case PrimitiveTypeCode.Int64Nullable: break;
case PrimitiveTypeCode.UInt64: break;
case PrimitiveTypeCode.UInt64Nullable: break;
case PrimitiveTypeCode.UInt64:
case PrimitiveTypeCode.UInt64Nullable:
case PrimitiveTypeCode.Int64:
case PrimitiveTypeCode.Int64Nullable:
PopulateInt64Value(reader, structure, descriptor, useTheReader);
break;
case PrimitiveTypeCode.Single:
case PrimitiveTypeCode.SingleNullable:
case PrimitiveTypeCode.Double:
Expand Down Expand Up @@ -338,6 +340,23 @@ internal static void PopulateInt32Value(EdiReader reader, EdiStructure structure
}
}
}
internal static void PopulateInt64Value(EdiReader reader, EdiStructure structure, EdiPropertyDescriptor descriptor, bool read) {
var cache = structure.CachedReads;
var valueInfo = descriptor.ValueInfo;
if (!descriptor.Info.PropertyType.IsEnum()) {
var integer = cache.ContainsPath(valueInfo.Path) ? cache.ReadAsInt64(valueInfo.Path, reader.Culture) :
read ? reader.ReadAsInt64() : (int?)reader.Value;
if (integer.HasValue) {
descriptor.Info.SetValue(structure.Instance, ConvertUtils.ConvertOrCast(integer.Value, CultureInfo.InvariantCulture, descriptor.Info.PropertyType));
}
} else {
var enumValueString = cache.ContainsPath(valueInfo.Path) ? cache.ReadAsString(valueInfo.Path) :
read ? reader.ReadAsString() : (string)reader.Value;
if (!string.IsNullOrEmpty(enumValueString)) {
descriptor.Info.SetValue(structure.Instance, ConvertUtils.ConvertOrCast(enumValueString, CultureInfo.InvariantCulture, descriptor.Info.PropertyType));
}
}
}

internal static void PopulateCharValue(EdiReader reader, EdiStructure structure, EdiPropertyDescriptor descriptor, bool read) {
var cache = structure.CachedReads;
Expand Down
8 changes: 8 additions & 0 deletions src/indice.Edi/EdiTextReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ public override bool Read() {
return ReadAsInt32Internal();
}

/// <summary>
/// Reads the next EDI token from the stream as a <see cref="Nullable{Int64}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Int64}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override long? ReadAsInt64() {
return ReadAsInt64Internal();
}

/// <summary>
/// Reads the next EDI token from the stream as a <see cref="String"/>.
/// </summary>
Expand Down
15 changes: 15 additions & 0 deletions src/indice.Edi/Serialization/EdiReadQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,21 @@ public static string ReadAsString(this Queue<EdiEntry> queue, string path) {
return integer;
}

public static long? ReadAsInt64(this Queue<EdiEntry> queue, string path, CultureInfo culture = null) {
var text = ReadAsString(queue, path);
if (text != null) {
text = text.TrimStart('Z'); // Z suppresses leading zeros
}
if (string.IsNullOrEmpty(text))
return null;

var integer = default(long);
if (!long.TryParse(text, NumberStyles.Integer, culture ?? CultureInfo.InvariantCulture, out integer)) {
throw new EdiException("Cannot parse int from string '{0}'. Path {1}".FormatWith(culture, text, path));
}
return integer;
}

public static decimal? ReadAsDecimal(this Queue<EdiEntry> queue, string path, Picture? picture, char? decimalMark) {
var text = ReadAsString(queue, path);
if (string.IsNullOrEmpty(text))
Expand Down
26 changes: 26 additions & 0 deletions test/indice.Edi.Tests/Models/ParseComponentValues_Interchange.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Text;
using indice.Edi.Serialization;

namespace indice.Edi.Tests.Models
{
public class ParseComponentValues_Interchange
{
public Message Msg { get; set; }

[EdiMessage]
public class Message
{
[EdiValue("9(1)", Path = "DTM/0")]
public int Integer { get; set; }

[EdiValue("9(8)", Path = "DTM/1", Format = "yyyyMMdd", Description = "DTM02 - Date (Format = CCYYMMDD)")]
[EdiValue("9(8)", Path = "DTM/2", Format = "HHmmssff", Description = "DTM03 - Time (Format = HHmmssff)")]
public DateTime DateTime { get; set; }

[EdiValue("9(1)", Path = "DTM/3")]
public long Long { get; set; }
}
}
}
24 changes: 14 additions & 10 deletions test/indice.Edi.Tests/ParseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,30 +68,34 @@ public void DateTimeFromString_Component_MaxLength_Exceeds_StringLength_Test(str
}

[Theory]
[InlineData("20170726", "2034", "2017-07-26T20:34:00Z")]
[InlineData("20170726", "20341", "2017-07-26T00:00:00Z")] // this should fail to parse the time part thus showing 00:00:00
[InlineData("20170726", "203406", "2017-07-26T20:34:06Z")]
[InlineData("20170726", "1558123", "2017-07-26T15:58:12.3Z")]
[InlineData("20170726", "15581234", "2017-07-26T15:58:12.34Z")]
[InlineData("20170726", "2034", "2017-07-26T20:34:00Z", "011", "08")]
[InlineData("20170726", "20341", "2017-07-26T00:00:00Z", "011", "08")] // this should fail to parse the time part thus showing 00:00:00
[InlineData("20170726", "203406", "2017-07-26T20:34:06Z", "011", "08")]
[InlineData("20170726", "1558123", "2017-07-26T15:58:12.3Z", "011", "08")]
[InlineData("20170726", "15581234", "2017-07-26T15:58:12.34Z", "011", "08")]
[Trait(Traits.Issue, "#130")]
public void DateTimeFromStringTestMiliseconds(string dateText, string timeText, string output) {
var expected = DateTime.Parse(output, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
[Trait(Traits.Issue, "#172")]
public void DateTimeFromStringTestMiliseconds(string dateText, string timeText, string expectedISODate, string intText, string longText) {
var expected = DateTime.Parse(expectedISODate, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
var grammar = EdiGrammar.NewX12();
var edi = $@"ISA*00*          *00*          *01*000123456      *ZZ*TEST2      *090827*0936*U*00401*000000055*0*T*>~
GS*PO*000123456*TEST2*20090827*1041*2*X*004010~
ST*850*0001~
DTM*011*{dateText}*{timeText}*08~
DTM*{intText}*{dateText}*{timeText}*{longText}~
SE*50*0001~
GE*1*2~
IEA*1*000000001~
";

var interchange = default(Interchange_Issue130);
var interchange = default(ParseComponentValues_Interchange);
using (var stream = Helpers.StreamFromString(edi)) {
interchange = new EdiSerializer().Deserialize<Interchange_Issue130>(new StreamReader(stream), grammar);
interchange = new EdiSerializer().Deserialize<ParseComponentValues_Interchange>(new StreamReader(stream), grammar);
}

Assert.Equal(expected, interchange.Msg.DateTime);
Assert.Equal(int.Parse(intText), interchange.Msg.Integer);
Assert.Equal(long.Parse(longText), interchange.Msg.Long);
}

}
}

0 comments on commit 8899926

Please sign in to comment.