Example #1
0
        /// <nodoc />
        public static Possible <ObservedPathSet, DeserializeFailure> TryDeserialize(
            PathTable pathTable,
            BuildXLReader reader,
            PathExpander pathExpander = null,
            Func <BuildXLReader, AbsolutePath> pathReader = null,
            Func <BuildXLReader, StringId> stringReader   = null)
        {
            PathTable.ExpandedAbsolutePathComparer comparer = pathTable.ExpandedPathComparer;

            int pathCount = reader.ReadInt32Compact();

            ObservedPathEntry[] paths = new ObservedPathEntry[pathCount];

            string       lastStr  = null;
            AbsolutePath lastPath = default(AbsolutePath);

            for (int i = 0; i < pathCount; i++)
            {
                var    flags = (ObservedPathEntryFlags)reader.ReadByte();
                string enumeratePatternRegex = null;
                if ((flags & ObservedPathEntryFlags.DirectoryEnumerationWithCustomPattern) != 0)
                {
                    enumeratePatternRegex = reader.ReadString();
                }
                else if ((flags & ObservedPathEntryFlags.DirectoryEnumerationWithAllPattern) != 0)
                {
                    enumeratePatternRegex = RegexDirectoryMembershipFilter.AllowAllRegex;
                }

                AbsolutePath newPath;
                string       full = null;

                if (pathReader != null)
                {
                    newPath = pathReader(reader);
                }
                else
                {
                    int reuseCount = reader.ReadInt32Compact();

                    if (reuseCount == 0)
                    {
                        full = reader.ReadString();
                    }
                    else
                    {
                        if (lastStr == null || lastStr.Length < reuseCount)
                        {
                            // This path set is invalid.
                            return(new DeserializeFailure($"Invalid reuseCount: {reuseCount}; last: '{lastStr}', last string length: {lastStr?.Length}"));
                        }

                        string partial = reader.ReadString();
                        full = lastStr.Substring(0, reuseCount) + partial;
                    }

                    if (!AbsolutePath.TryCreate(pathTable, full, out newPath))
                    {
                        // It might be failed due to the tokenized path.
                        if (pathExpander == null || !pathExpander.TryCreatePath(pathTable, full, out newPath))
                        {
                            return(new DeserializeFailure($"Invalid path: '{full}'"));
                        }
                    }
                }

                paths[i] = new ObservedPathEntry(newPath, flags, enumeratePatternRegex);

                if (lastPath.IsValid)
                {
#if DEBUG
                    if (comparer.Compare(lastPath, newPath) >= 0)
                    {
                        return(new DeserializeFailure($"Paths not sorted: " +
                                                      $"old = '{lastPath.ToString(pathTable)}', new = '{newPath.ToString(pathTable)}';" +
                                                      $"old str = '{lastStr}', new str = '{full}'"));
                    }
#endif
                }

                lastPath = newPath;
                lastStr  = full;
            }

            int        fileNameCount = reader.ReadInt32Compact();
            StringId[] fileNames     = new StringId[fileNameCount];
            for (int i = 0; i < fileNameCount; i++)
            {
                fileNames[i] = stringReader?.Invoke(reader) ?? StringId.Create(pathTable.StringTable, reader.ReadString());
            }

            // Read unsafe options
            var unsafeOptions = UnsafeOptions.TryDeserialize(reader);
            if (unsafeOptions == null)
            {
                return(new DeserializeFailure("UnsafeOptions are null"));
            }

            // Note that we validated sort order above.
            return(new ObservedPathSet(
                       SortedReadOnlyArray <ObservedPathEntry, ObservedPathEntryExpandedPathComparer> .FromSortedArrayUnsafe(
                           ReadOnlyArray <ObservedPathEntry> .FromWithoutCopy(paths),
                           new ObservedPathEntryExpandedPathComparer(comparer)),
                       SortedReadOnlyArray <StringId, CaseInsensitiveStringIdComparer> .FromSortedArrayUnsafe(
                           ReadOnlyArray <StringId> .FromWithoutCopy(fileNames),
                           new CaseInsensitiveStringIdComparer(pathTable.StringTable)),
                       unsafeOptions));
        }