Files
DotNetAlpm/Alpm/EnumerableWrapper`3.cs
2020-04-29 23:47:06 -04:00

120 lines
3.5 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Foodsoft.Alpm
{
internal static class EnumerableWrapper<TElement>
{
internal static EnumerableWrapper<TElement, TImpl> Create<TImpl>(TImpl impl)
where TImpl : struct, ICollectionImpl<TElement>
{
return new EnumerableWrapper<TElement, TImpl>(impl);
}
}
internal struct EnumerableWrapper<TElement, TImpl> : ICollection<TElement> where TImpl : struct,
ICollectionImpl<TElement>
{
private TImpl _impl;
public static EnumerableWrapper<TElement, TImpl> Create(TImpl impl)
{
return new EnumerableWrapper<TElement, TImpl>(impl);
}
public EnumerableWrapper(TImpl impl)
{
_impl = impl;
}
public IEnumerator<TElement> GetEnumerator()
{
var handle = _impl.Handle;
var release = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
handle.DangerousAddRef(ref release);
if (!release) throw new ObjectDisposedException(_impl.GetType().FullName);
for (var list = _impl.GetItems(); list != IntPtr.Zero; list = Wrapper.ListNext(list))
{
yield return _impl.PtrToItem(Wrapper.ListData(list));
}
}
finally
{
if (release)
handle.DangerousRelease();
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public int Count
{
get
{
var impl = _impl;
return impl.Handle.UseHandle((_) => (int) alpm.alpm_list_count(impl.GetItems()));
}
}
public bool Contains(TElement item)
{
var impl = _impl;
switch (item)
{
case string s:
return impl.Handle.UseHandle((_) => alpm.alpm_list_find_str(impl.GetItems(), s) != (IntPtr.Zero));
default:
var comparer = EqualityComparer<TElement>.Default;
return _impl.Handle.UseHandle((_) =>
{
for (var list = impl.GetItems(); list != IntPtr.Zero; list = Wrapper.ListNext(list))
{
if (comparer.Equals(item, impl.PtrToItem(Wrapper.ListData(list))))
return true;
}
return false;
});
}
}
public void CopyTo(TElement[] array, int arrayIndex)
{
var impl = _impl;
impl.Handle.UseHandle((_) =>
{
for (var list = impl.GetItems(); list != IntPtr.Zero; list = Wrapper.ListNext(list))
{
array[arrayIndex++] = impl.PtrToItem(Wrapper.ListData(list));
}
return arrayIndex;
});
}
public void Add(TElement item)
{
throw new NotSupportedException();
}
public void Clear()
{
throw new NotSupportedException();
}
public bool Remove(TElement item)
{
throw new NotSupportedException();
}
public bool IsReadOnly => true;
}
}