< Summary

Class:SharpHoundCommonLib.Extensions
Assembly:SharpHoundCommonLib
File(s):D:\a\SharpHoundCommon\SharpHoundCommon\src\CommonLib\Extensions.cs
Covered lines:63
Uncovered lines:55
Coverable lines:118
Total lines:219
Line coverage:53.3% (63 of 118)
Covered branches:25
Total branches:52
Branch coverage:48% (25 of 52)

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.cctor()100%10100%
ToListAsync()50%8088.88%
ToArrayAsync()0%800%
FirstOrDefaultAsync()58.33%12085.71%
FirstOrDefaultAsync()50%12085.71%
DefaultIfEmpty(...)100%10100%
.ctor(...)100%10100%
GetAsyncEnumerator(...)100%10100%
.ctor(...)100%10100%
DisposeAsync()100%20100%
MoveNextAsync()100%60100%
ToAsyncEnumerable(...)0%200%
.ctor(...)100%100%
GetAsyncEnumerator(...)100%100%
.ctor(...)100%100%
DisposeAsync()100%100%
MoveNextAsync()0%200%
LdapValue(...)100%100%
LdapValue(...)100%100%
IsComputerCollectionSet(...)100%100%
IsLocalGroupCollectionSet(...)100%100%
Rid(...)100%10100%
ToDirectoryObject(...)100%10100%

File(s)

D:\a\SharpHoundCommon\SharpHoundCommon\src\CommonLib\Extensions.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.DirectoryServices;
 4using System.Linq;
 5using System.Security.Principal;
 6using System.Threading;
 7using System.Threading.Tasks;
 8using Microsoft.Extensions.Logging;
 9using SharpHoundCommonLib.Enums;
 10
 11namespace SharpHoundCommonLib
 12{
 13    public static class Extensions
 14    {
 15        private static readonly ILogger Log;
 16
 17        static Extensions()
 118        {
 119            Log = Logging.LogProvider.CreateLogger("Extensions");
 120        }
 21
 22        public static async Task<List<T>> ToListAsync<T>(this IAsyncEnumerable<T> items)
 423        {
 424            if (items == null) {
 025                return new List<T>();
 26            }
 427            var results = new List<T>();
 1628            await foreach (var item in items
 429                               .ConfigureAwait(false))
 230                results.Add(item);
 431            return results;
 432        }
 33
 34        public static async Task<T[]> ToArrayAsync<T>(this IAsyncEnumerable<T> items)
 035        {
 036            if (items == null) {
 037                return Array.Empty<T>();
 38            }
 039            var results = new List<T>();
 040            await foreach (var item in items
 041                               .ConfigureAwait(false))
 042                results.Add(item);
 043            return results.ToArray();
 044        }
 45
 46        public static async Task<T> FirstOrDefaultAsync<T>(this IAsyncEnumerable<T> source,
 1047            CancellationToken cancellationToken = default) {
 1048            if (source == null) {
 049                return default;
 50            }
 51
 2052            await using (var enumerator = source.GetAsyncEnumerator(cancellationToken)) {
 1053                var first = await enumerator.MoveNextAsync() ? enumerator.Current : default;
 1054                return first;
 55            }
 1056        }
 57
 58        public static async Task<T> FirstOrDefaultAsync<T>(this IAsyncEnumerable<T> source, T defaultValue,
 159            CancellationToken cancellationToken = default) {
 160            if (source == null) {
 061                return defaultValue;
 62            }
 63
 264            await using (var enumerator = source.GetAsyncEnumerator(cancellationToken)) {
 165                var first = await enumerator.MoveNextAsync() ? enumerator.Current : defaultValue;
 166                return first;
 67            }
 168        }
 69
 70        public static IAsyncEnumerable<T> DefaultIfEmpty<T>(this IAsyncEnumerable<T> source,
 871            T defaultValue, CancellationToken cancellationToken = default) {
 872            return new DefaultIfEmptyAsyncEnumerable<T>(source, defaultValue);
 873        }
 74
 75        private sealed class DefaultIfEmptyAsyncEnumerable<T> : IAsyncEnumerable<T> {
 76            private readonly DefaultIfEmptyAsyncEnumerator<T> _enumerator;
 1677            public DefaultIfEmptyAsyncEnumerable(IAsyncEnumerable<T> source, T defaultValue) {
 878                _enumerator = new DefaultIfEmptyAsyncEnumerator<T>(source, defaultValue);
 879            }
 880            public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken())
 881                return _enumerator;
 882            }
 83        }
 84
 85        private sealed class DefaultIfEmptyAsyncEnumerator<T> : IAsyncEnumerator<T> {
 86            private readonly IAsyncEnumerable<T> _source;
 87            private readonly T _defaultValue;
 88            private T _current;
 89            private bool _enumeratorDisposed;
 90
 91            private IAsyncEnumerator<T> _enumerator;
 92
 1693            public DefaultIfEmptyAsyncEnumerator(IAsyncEnumerable<T> source, T defaultValue) {
 894                _source = source;
 895                _defaultValue = defaultValue;
 896            }
 97
 1398            public async ValueTask DisposeAsync() {
 1399                _enumeratorDisposed = true;
 21100                if (_enumerator != null) {
 8101                    await _enumerator.DisposeAsync().ConfigureAwait(false);
 8102                    _enumerator = null;
 8103                }
 13104            }
 105
 9106            public async ValueTask<bool> MoveNextAsync() {
 10107                if (_enumeratorDisposed) {
 1108                    return false;
 109                }
 8110                _enumerator ??= _source.GetAsyncEnumerator();
 111
 10112                if (await _enumerator.MoveNextAsync().ConfigureAwait(false)) {
 2113                    _current = _enumerator.Current;
 2114                    return true;
 115                }
 116
 6117                _current = _defaultValue;
 6118                await DisposeAsync().ConfigureAwait(false);
 6119                return true;
 9120            }
 121
 8122            public T Current => _current;
 123        }
 124
 0125        internal static IAsyncEnumerable<T> ToAsyncEnumerable<T>(this IEnumerable<T> source) {
 0126            return source switch {
 0127                ICollection<T> collection => new IAsyncEnumerableCollectionAdapter<T>(collection),
 0128                _ => null
 0129            };
 0130        }
 131
 132        private sealed class IAsyncEnumerableCollectionAdapter<T> : IAsyncEnumerable<T> {
 133            private readonly IAsyncEnumerator<T> _enumerator;
 134
 0135            public IAsyncEnumerableCollectionAdapter(ICollection<T> source) {
 0136                _enumerator = new IAsyncEnumeratorCollectionAdapter<T>(source);
 0137            }
 0138            public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken())
 0139                return _enumerator;
 0140            }
 141        }
 142
 143        private sealed class IAsyncEnumeratorCollectionAdapter<T> : IAsyncEnumerator<T> {
 144            private readonly IEnumerable<T> _source;
 145            private IEnumerator<T> _enumerator;
 146
 0147            public IAsyncEnumeratorCollectionAdapter(ICollection<T> source) {
 0148                _source = source;
 0149            }
 150
 0151            public ValueTask DisposeAsync() {
 0152                _enumerator = null;
 0153                return new ValueTask(Task.CompletedTask);
 0154            }
 155
 0156            public ValueTask<bool> MoveNextAsync() {
 0157                if (_enumerator == null) {
 0158                    _enumerator = _source.GetEnumerator();
 0159                }
 0160                return new ValueTask<bool>(_enumerator.MoveNext());
 0161            }
 162
 0163            public T Current => _enumerator.Current;
 164        }
 165
 166
 167        public static string LdapValue(this SecurityIdentifier s)
 0168        {
 0169            var bytes = new byte[s.BinaryLength];
 0170            s.GetBinaryForm(bytes, 0);
 171
 0172            var output = $"\\{BitConverter.ToString(bytes).Replace('-', '\\')}";
 0173            return output;
 0174        }
 175
 176        public static string LdapValue(this Guid s)
 0177        {
 0178            var bytes = s.ToByteArray();
 0179            var output = $"\\{BitConverter.ToString(bytes).Replace('-', '\\')}";
 0180            return output;
 0181        }
 182
 183        /// <summary>
 184        ///     Returns true if any computer collection methods are set
 185        /// </summary>
 186        /// <param name="methods"></param>
 187        /// <returns></returns>
 0188        public static bool IsComputerCollectionSet(this CollectionMethod methods) {
 189            const CollectionMethod test = CollectionMethod.ComputerOnly | CollectionMethod.LoggedOn;
 0190            return (methods & test) != 0;
 0191        }
 192
 193        /// <summary>
 194        ///     Returns true if any local group collections are set
 195        /// </summary>
 196        /// <param name="methods"></param>
 197        /// <returns></returns>
 198        public static bool IsLocalGroupCollectionSet(this CollectionMethod methods)
 0199        {
 0200            return (methods & CollectionMethod.LocalGroups) != 0;
 0201        }
 202
 203        /// <summary>
 204        ///     Gets the relative identifier for a SID
 205        /// </summary>
 206        /// <param name="securityIdentifier"></param>
 207        /// <returns></returns>
 208        public static int Rid(this SecurityIdentifier securityIdentifier)
 5209        {
 5210            var value = securityIdentifier.Value;
 5211            var rid = int.Parse(value.Substring(value.LastIndexOf("-", StringComparison.Ordinal) + 1));
 5212            return rid;
 5213        }
 214
 1215        public static IDirectoryObject ToDirectoryObject(this DirectoryEntry entry) {
 1216            return new DirectoryEntryWrapper(entry);
 1217        }
 218    }
 219}