File: Serialization\SerializerService_ChecksumWithChildren.cs
Web Access
Project: ..\..\..\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.Serialization
{
    /// <summary>
    /// serialize and deserialize objects to straem.
    /// some of these could be moved into actual object, but putting everything here is a bit easier to find I believe.
    /// </summary>
    internal partial class SerializerService
    {
        private const byte ChecksumKind = 0;
        private const byte ChecksumWithChildrenKind = 1;
 
        private static readonly ImmutableDictionary<WellKnownSynchronizationKind, Func<ImmutableArray<object>, ChecksumWithChildren>> s_creatorMap = CreateCreatorMap();
 
        public void SerializeChecksumWithChildren(ChecksumWithChildren checksums, ObjectWriter writer, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
 
            var kind = checksums.GetWellKnownSynchronizationKind();
            writer.WriteInt32((int)kind);
            checksums.Checksum.WriteTo(writer);
 
            writer.WriteInt32(checksums.Children.Length);
            foreach (var child in checksums.Children)
            {
                switch (child)
                {
                    case Checksum checksum:
                        writer.WriteByte(ChecksumKind);
                        checksum.WriteTo(writer);
                        continue;
                    case ChecksumCollection checksumCollection:
                        writer.WriteByte(ChecksumWithChildrenKind);
                        SerializeChecksumWithChildren(checksumCollection, writer, cancellationToken);
                        continue;
                }
 
                throw ExceptionUtilities.UnexpectedValue(child);
            }
        }
 
        private ChecksumWithChildren DeserializeChecksumWithChildren(ObjectReader reader, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
 
            var kind = (WellKnownSynchronizationKind)reader.ReadInt32();
            var checksum = Checksum.ReadFrom(reader);
 
            var childrenCount = reader.ReadInt32();
            var children = ImmutableArray.CreateBuilder<object>(childrenCount);
 
            for (var i = 0; i < childrenCount; i++)
            {
                var childKind = reader.ReadByte();
                if (childKind == ChecksumKind)
                {
                    children.Add(Checksum.ReadFrom(reader));
                }
                else if (childKind == ChecksumWithChildrenKind)
                {
                    children.Add(DeserializeChecksumWithChildren(reader, cancellationToken));
                }
                else
                {
                    throw ExceptionUtilities.UnexpectedValue(childKind);
                }
            }
 
            var checksums = s_creatorMap[kind](children.MoveToImmutable());
            Contract.ThrowIfFalse(checksums.Checksum == checksum);
 
            return checksums;
        }
 
        private static ImmutableDictionary<WellKnownSynchronizationKind, Func<ImmutableArray<object>, ChecksumWithChildren>> CreateCreatorMap()
        {
            return ImmutableDictionary<WellKnownSynchronizationKind, Func<ImmutableArray<object>, ChecksumWithChildren>>.Empty
                .Add(WellKnownSynchronizationKind.SolutionState, children => new SolutionStateChecksums(children))
                .Add(WellKnownSynchronizationKind.ProjectState, children => new ProjectStateChecksums(children))
                .Add(WellKnownSynchronizationKind.DocumentState, children => new DocumentStateChecksums(children))
                .Add(WellKnownSynchronizationKind.ChecksumCollection, children => new ChecksumCollection(children));
        }
    }
}