Exemplo n.º 1
0
 public static void Save(this ITreeSerializable item, Stream stream, TreeFormat format, TreeSerializationSettings settings = null)
 {
     using (ITreeWriter writer = TreeSerializer.Writer(format, stream, settings))
     {
         item.Write(writer);
     }
 }
Exemplo n.º 2
0
        // Write item, then read back and return size diagnostics instead of round-tripped instance
        public static TreeDiagnostics Diagnostics <T>(T value, Func <T> buildT, TreeFormat format) where T : ITreeSerializable
        {
            TreeSerializationSettings settings = new TreeSerializationSettings()
            {
                LeaveStreamOpen = true
            };

            using (MemoryStream stream = new MemoryStream())
            {
                using (ITreeWriter writer = Writer(format, stream, settings))
                {
                    value.Write(writer);
                }

                stream.Seek(0, SeekOrigin.Begin);

                using (TreeDiagnosticsReader reader = new TreeDiagnosticsReader(Reader(format, stream, settings)))
                {
                    T roundTripped = buildT();
                    roundTripped.Read(reader);

                    // Test double dispose
                    reader.Dispose();

                    return(reader.Tree);
                }
            }
        }
Exemplo n.º 3
0
 public static void Load(this ITreeSerializable item, Stream stream, TreeFormat format, TreeSerializationSettings settings = null)
 {
     using (ITreeReader reader = TreeSerializer.Reader(format, stream, settings))
     {
         item.Read(reader);
     }
 }
Exemplo n.º 4
0
 // Use default constructor if available
 public static T RoundTrip <T>(
     T value,
     TreeFormat format,
     TreeSerializationSettings settings = null,
     bool testDoubleDispose             = false) where T : ITreeSerializable, new()
 {
     return(RoundTrip(value, () => new T(), format, settings, testDoubleDispose));
 }
Exemplo n.º 5
0
        public static void VerifySkip <T>(T value, TreeFormat format) where T : ITreeSerializable
        {
            // Test serialization details
            using (MemoryStream stream = new MemoryStream())
            {
                TreeSerializationSettings settings = new TreeSerializationSettings()
                {
                    LeaveStreamOpen = true
                };

                using (ITreeWriter writer = Writer(format, stream, settings))
                {
                    value.Write(writer);
                }

                long bytesWritten = stream.Position;

                // Read tokens individually and verify 'None' returned at end
                stream.Seek(0, SeekOrigin.Begin);
                using (ITreeReader reader = Reader(format, stream, settings))
                {
                    while (reader.Read())
                    {
                        // Verify each token type is coming back properly (no reading random bytes)
                        Assert.True((byte)reader.TokenType <= (byte)TreeToken.BlockArray);
                    }

                    Assert.Equal(TreeToken.None, reader.TokenType);
                    Assert.Equal(bytesWritten, stream.Position);
                }

                // Verify Skip once skips everything (each ITreeSerializable must be one value or one root array or object
                stream.Seek(0, SeekOrigin.Begin);
                using (ITreeReader reader = Reader(format, stream, settings))
                {
                    reader.Skip();
                    Assert.Equal(TreeToken.None, reader.TokenType);
                    Assert.Equal(bytesWritten, stream.Position);
                }

                // For objects, verify each property can be skipped correctly
                // Each Skip should read the value, so that the next token is the next PropertyName
                stream.Seek(0, SeekOrigin.Begin);
                using (ITreeReader reader = Reader(format, stream, settings))
                {
                    if (reader.TokenType == TreeToken.StartObject)
                    {
                        Empty empty = new Empty();
                        empty.Read(reader);

                        Assert.Equal(bytesWritten, stream.Position);
                    }
                }
            }
        }
Exemplo n.º 6
0
        public static ITreeWriter Writer(TreeFormat format, Stream stream, TreeSerializationSettings settings)
        {
            switch (format)
            {
            case TreeFormat.Binary:
                return(new BinaryTreeWriter(stream, settings));

            case TreeFormat.Json:
                return(new JsonTreeWriter(stream, settings));

            default:
                throw new NotImplementedException($"Writer doesn't know how to build for '{format}'.");
            }
        }
Exemplo n.º 7
0
        private static TreeFormat InvertType(TreeFormat Format)
        {
            switch (Format)
            {
            case TreeFormat.Les:
                return(TreeFormat.Blt);

            case TreeFormat.Blt:
                return(TreeFormat.Les);

            default:
                return(TreeFormat.Unknown);
            }
        }
Exemplo n.º 8
0
        public static void RoundTripArray <T>(T[] sample, TreeFormat format) where T : unmanaged
        {
            // Wrap primitive array in a contained implementing ITreeSerializable
            // and calling WriteBlockArray / ReadBlockArray
            ArrayContainer <T> arrayContainer = new ArrayContainer <T>(sample);

            // Verify roundtrip reconstructs array properly
            ArrayContainer <T> roundTripped = RoundTrip(arrayContainer, format);

            arrayContainer.AssertEqual(roundTripped);

            // Verify Skip correct for each block array type
            VerifySkip(arrayContainer, format);
        }
Exemplo n.º 9
0
        private static string GetExtension(TreeFormat Format)
        {
            switch (Format)
            {
            case TreeFormat.Les:
                return(".les");

            case TreeFormat.Blt:
                return(".blt");

            case TreeFormat.Unknown:
            default:
                return(string.Empty);
            }
        }
Exemplo n.º 10
0
        private static void TestIntegers(TreeFormat format)
        {
            TreeSerializationSettings settings = new TreeSerializationSettings()
            {
                LeaveStreamOpen = true
            };

            using (MemoryStream stream = new MemoryStream())
            {
                using (ITreeWriter writer = Writer(format, stream, settings))
                {
                    writer.WriteStartArray();

                    for (int i = -1; i < 300; i += 7)
                    {
                        writer.WriteValue(i);
                    }

                    writer.WriteEndArray();
                }

                long bytesWritten = stream.Position;
                stream.Seek(0, SeekOrigin.Begin);

                using (ITreeReader reader = Reader(format, stream, settings))
                {
                    Assert.Equal(TreeToken.StartArray, reader.TokenType);

                    for (int i = -1; i < 300; i += 7)
                    {
                        Assert.True(reader.Read());
                        Assert.Equal(TreeToken.Integer, reader.TokenType);
                        Assert.Equal(i, reader.ReadAsInt32());
                    }

                    Assert.True(reader.Read());
                    Assert.Equal(TreeToken.EndArray, reader.TokenType);
                    Assert.False(reader.Read());
                }

                Assert.Equal(bytesWritten, stream.Position);
            }
        }
Exemplo n.º 11
0
        // RoundTrip with all verification
        public static T RoundTrip_NullSettings <T>(T value, TreeFormat format) where T : ITreeSerializable, new()
        {
            T roundTripped = new T();

            byte[] buffer = null;

            using (MemoryStream stream = new MemoryStream())
            {
                using (ITreeWriter writer = Writer(format, stream, null))
                {
                    // Writer must initialize settings property even if constructed with null.
                    Assert.NotNull(writer.Settings);

                    value.Write(writer);
                }

                // Get bytes to read back from with reader
                buffer = stream.ToArray();
            }

            using (MemoryStream stream = new MemoryStream(buffer))
            {
                using (ITreeReader reader = Reader(format, stream, null))
                {
                    // Reader must initialize settings property even if constructed with null.
                    Assert.NotNull(reader.Settings);

                    roundTripped.Read(reader);

                    // Verify everything read back
                    Assert.Equal(buffer.Length, stream.Position);
                }
            }

            return(roundTripped);
        }
Exemplo n.º 12
0
        // Reference RoundTrip implementation - no extra verification
        private static T RoundTrip_Basic <T>(T value, Func <T> buildT, TreeFormat format) where T : ITreeSerializable
        {
            TreeSerializationSettings settings = new TreeSerializationSettings()
            {
                LeaveStreamOpen = true
            };

            using (MemoryStream stream = new MemoryStream())
            {
                using (ITreeWriter writer = Writer(format, stream, settings))
                {
                    value.Write(writer);
                }

                stream.Seek(0, SeekOrigin.Begin);

                using (ITreeReader reader = Reader(format, stream, settings))
                {
                    T roundTripped = buildT();
                    roundTripped.Read(reader);
                    return(roundTripped);
                }
            }
        }
Exemplo n.º 13
0
 private static string GetExtension(TreeFormat Format)
 {
     switch (Format)
     {
         case TreeFormat.Les:
             return ".les";
         case TreeFormat.Blt:
             return ".blt";
         case TreeFormat.Unknown:
         default:
             return string.Empty;
     }
 }
Exemplo n.º 14
0
 private static TreeFormat InvertType(TreeFormat Format)
 {
     switch (Format)
     {
         case TreeFormat.Les:
             return TreeFormat.Blt;
         case TreeFormat.Blt:
             return TreeFormat.Les;
         default:
             return TreeFormat.Unknown;
     }
 }
Exemplo n.º 15
0
 public static TreeDiagnostics Diagnostics <T>(T value, TreeFormat format) where T : ITreeSerializable, new()
 {
     return(Diagnostics(value, () => new T(), format));
 }
Exemplo n.º 16
0
        // RoundTrip with all verification
        public static T RoundTrip <T>(
            T value,
            Func <T> buildT,
            TreeFormat format,
            TreeSerializationSettings settings = null,
            bool testDoubleDispose             = false) where T : ITreeSerializable
        {
            T roundTripped = buildT();

            // Request non-compact stream (debuggability)
            settings ??= new TreeSerializationSettings()
            {
                Verbose = true
            };

            byte[] buffer = null;

            using (MemoryStream stream = new MemoryStream())
            {
                using (ITreeWriter writer = Writer(format, stream, settings))
                {
                    value.Write(writer);

                    // Debuggability: To see serialized text
                    //string serializedText = StreamString(stream);

                    if (testDoubleDispose)
                    {
                        writer.Dispose();
                    }
                }

                if (!settings.LeaveStreamOpen)
                {
                    // Verify stream disposed
                    if (!Debugger.IsAttached)
                    {
                        Assert.Throws <ObjectDisposedException>(() => stream.Position);
                    }
                }
                else
                {
                    // Verify stream left open if requested
                    long verifyStreamNotDisposed = stream.Position;
                }

                // Get bytes to read back from with reader
                buffer = stream.ToArray();
            }

            using (MemoryStream stream = new MemoryStream(buffer))
            {
                using (ITreeReader reader = Reader(format, stream, settings))
                {
                    // Ensure Readers pre-read first token by default
                    // Needed to allow single value reading to work without everything having to handle this case everywhere
                    Assert.NotEqual(TreeToken.None, reader.TokenType);

                    roundTripped.Read(reader);

                    // Verify everything read back
                    Assert.Equal(buffer.Length, stream.Position);

                    if (testDoubleDispose)
                    {
                        reader.Dispose();
                    }
                }

                if (!settings.LeaveStreamOpen)
                {
                    // Verify stream disposed
                    if (!Debugger.IsAttached)
                    {
                        Assert.Throws <ObjectDisposedException>(() => stream.Position);
                    }
                }
                else
                {
                    // Verify stream left open if requested
                    long verifyStreamNotDisposed = stream.Position;
                }
            }

            return(roundTripped);
        }
Exemplo n.º 17
0
 public static void Load(this ITreeSerializable item, string filePath, TreeFormat format, TreeSerializationSettings settings = null)
 {
     Load(item, File.OpenRead(filePath), format, settings);
 }
Exemplo n.º 18
0
 public static void Save(this ITreeSerializable item, string filePath, TreeFormat format, TreeSerializationSettings settings = null)
 {
     Save(item, File.Create(filePath), format, settings);
 }
Exemplo n.º 19
0
        public static void Basics(TreeFormat format)
        {
            Random r = new Random();

            // Test integers with specific values (for varying length encodings)
            TestIntegers(format);

            // Test serialization of each primitive value type (bool, string, long, double)
            Sample sample = new Sample(new Random());

            sample.AssertEqual(RoundTrip <Sample>(sample, format));

            // Test serialization of containers (read must leave last token of nested items so loop finds next property name properly)
            SingleContainer <Sample> container = new SingleContainer <Sample>(sample);

            container.AssertEqual(RoundTrip <SingleContainer <Sample> >(container, format));

            // Test diagnostics doesn't throw when over Reader
            TreeDiagnostics diagnostics = Diagnostics(sample, format);

            // Test serialization of all supported primitive array types
            RoundTripArray(new byte[] { 0, 4, 16 }, format);
            RoundTripArray(new char[] { 'S', 'o', 'A' }, format);
            RoundTripArray(new sbyte[] { 0, 4, 16 }, format);
            RoundTripArray(new ushort[] { 0, 4, 16 }, format);
            RoundTripArray(new short[] { 0, 4, 16 }, format);
            RoundTripArray(new uint[] { 0, 4, 16 }, format);
            RoundTripArray(new int[] { 0, 4, 16 }, format);
            RoundTripArray(new ulong[] { 0, 4, 16 }, format);
            RoundTripArray(new long[] { 0, 4, 16 }, format);
            RoundTripArray(new float[] { 0.0f, 100.5f, -2.05f }, format);
            RoundTripArray(new double[] { 0.0f, 100.5f, -2.05f }, format);

            // Verify exception on (expected) unsupported type
            Assert.Throws <NotSupportedException>(() => RoundTripArray(new decimal[] { 0.01M, 0.02M }, format));

            // Null/Empty array handling (currently expected to come back as empty array)
            RoundTripArray <byte>(null, format);
            RoundTripArray <byte>(new byte[] { }, format);

            // Test double Dispose handled correctly, 'Verbose == true' works, 'LeaveStreamOpen' respected
            container.AssertEqual(RoundTrip(container, format, testDoubleDispose: true));
            container.AssertEqual(RoundTrip(container, format, new TreeSerializationSettings()
            {
                LeaveStreamOpen = true
            }));
            container.AssertEqual(RoundTrip(container, format, new TreeSerializationSettings()
            {
                Verbose = true
            }));

            // Test null string handling
            sample.Name = null;
            sample.AssertEqual(RoundTrip(sample, format));

            // Test settings defaulting
            sample.AssertEqual(RoundTrip_NullSettings(sample, format));

            // Test Skip behavior works for each primitive value
            VerifySkip(sample, format);

            // Test serialization details
            using (MemoryStream stream = new MemoryStream())
            {
                TreeSerializationSettings settings = new TreeSerializationSettings()
                {
                    LeaveStreamOpen = true
                };

                using (ITreeWriter writer = Writer(format, stream, settings))
                {
                    sample.Write(writer);
                }

                long bytesWritten = stream.Position;
                stream.Seek(0, SeekOrigin.Begin);

                using (ITreeReader reader = Reader(format, stream, settings))
                {
                    // Test 'Expect' throwing (should not be 'None' when file just opened)
                    Assert.NotEqual(TreeToken.None, reader.TokenType);
                    Assert.Throws <IOException>(() => reader.Expect(TreeToken.None));

                    // Test reading back as wrong type (exception from ReadObject unexpected property name)
                    Assert.Throws <IOException>(() => new SingleContainer <Sample>().Read(reader));
                }
            }
        }