< Summary

Information
Class: Ice.Internal.Patcher.InvokeInfo
Assembly: Ice
File(s): /home/runner/work/ice/ice/csharp/src/Ice/Internal/Patcher.cs
Tag: 71_18251537082
Line coverage
52%
Covered lines: 11
Uncovered lines: 10
Coverable lines: 21
Total lines: 136
Line coverage: 52.3%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage
75%
Covered methods: 3
Total methods: 4
Method coverage: 75%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
getCount(...)100%1.13150%
invokeAdd(...)100%1.04166.67%
invokeSet(...)100%210%

File(s)

/home/runner/work/ice/ice/csharp/src/Ice/Internal/Patcher.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3#nullable enable
 4
 5using System.Reflection;
 6
 7namespace Ice.Internal;
 8
 9public sealed class Patcher
 10{
 11    public static System.Action<T?> arrayReadValue<T>(T?[] arr, int index) where
 12        T : Ice.Value => (T? v) => arr[index] = v;
 13
 14    public static System.Action<T?> listReadValue<T>(List<T?> seq, int index) where T : Ice.Value
 15    {
 16        return (T? v) =>
 17        {
 18            int count = seq.Count;
 19            if (index >= count) // Need to grow the sequence.
 20            {
 21                for (int i = count; i < index; i++)
 22                {
 23                    seq.Add(null);
 24                }
 25                seq.Add(v);
 26            }
 27            else
 28            {
 29                seq[index] = v;
 30            }
 31        };
 32    }
 33
 34    public static System.Action<T?> customSeqReadValue<T>(IEnumerable<T?> seq, int index) where T : Ice.Value
 35    {
 36        return (T? v) =>
 37        {
 38            InvokeInfo info = getInvokeInfo<T>(seq.GetType());
 39            int count = info.getCount(seq);
 40            if (index >= count) // Need to grow the sequence.
 41            {
 42                for (int i = count; i < index; i++)
 43                {
 44                    info.invokeAdd(seq, null);
 45                }
 46                info.invokeAdd(seq, v);
 47            }
 48            else
 49            {
 50                info.invokeSet(seq, index, v);
 51            }
 52        };
 53    }
 54
 55    private static InvokeInfo getInvokeInfo<T>(Type t)
 56    {
 57        lock (_methodTable)
 58        {
 59            if (_methodTable.TryGetValue(t, out InvokeInfo? i))
 60            {
 61                return i;
 62            }
 63
 64            MethodInfo? am = t.GetMethod("Add", [typeof(T)]) ??
 65                throw new Ice.MarshalException("Cannot patch a collection without an Add() method");
 66            PropertyInfo? pi = t.GetProperty("Item") ??
 67                throw new Ice.MarshalException("Cannot patch a collection without an indexer");
 68            MethodInfo? sm = pi.GetSetMethod() ??
 69                throw new Ice.MarshalException("Cannot patch a collection without an indexer to set a value");
 70            pi = t.GetProperty("Count");
 71            if (pi == null)
 72            {
 73                throw new Ice.MarshalException("Cannot patch a collection without a Count property");
 74            }
 75            MethodInfo? cm = pi.GetGetMethod() ??
 76                throw new Ice.MarshalException("Cannot patch a collection without a readable Count property");
 77            i = new InvokeInfo(am, sm, cm);
 78            _methodTable.Add(t, i);
 79            return i;
 80        }
 81    }
 82
 83    private class InvokeInfo
 84    {
 185        public InvokeInfo(MethodInfo am, MethodInfo sm, MethodInfo cm)
 86        {
 187            _addMethod = am;
 188            _setMethod = sm;
 189            _countMethod = cm;
 190        }
 91
 92        internal int getCount(System.Collections.IEnumerable seq)
 93        {
 94            try
 95            {
 196                return (int)_countMethod.Invoke(seq, null)!;
 97            }
 098            catch (System.Exception ex)
 99            {
 0100                throw new Ice.MarshalException("Could not read Count property during patching", ex);
 101            }
 1102        }
 103
 104        internal void invokeAdd(System.Collections.IEnumerable seq, object? v)
 105        {
 106            try
 107            {
 1108                object?[] arg = new object?[] { v };
 1109                _addMethod.Invoke(seq, arg);
 1110            }
 0111            catch (System.Exception ex)
 112            {
 0113                throw new Ice.MarshalException("Could not invoke Add method during patching", ex);
 114            }
 1115        }
 116
 117        internal void invokeSet(System.Collections.IEnumerable seq, int index, object? v)
 118        {
 119            try
 120            {
 0121                object?[] args = new object?[] { index, v };
 0122                _setMethod.Invoke(seq, args);
 0123            }
 0124            catch (System.Exception ex)
 125            {
 0126                throw new Ice.MarshalException("Could not call indexer during patching", ex);
 127            }
 0128        }
 129
 130        private readonly MethodInfo _addMethod;
 131        private readonly MethodInfo _setMethod;
 132        private readonly MethodInfo _countMethod;
 133    }
 134
 135    private static readonly Dictionary<Type, InvokeInfo> _methodTable = new Dictionary<Type, InvokeInfo>();
 136}