namespace Python.Runtime.Codecs
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
///
/// Represents a group of s. Useful to group them by priority.
///
public sealed class DecoderGroup: IPyObjectDecoder, IEnumerable, IDisposable
{
readonly List decoders = new();
///
/// Add specified decoder to the group
///
public void Add(IPyObjectDecoder item)
{
if (item is null) throw new ArgumentNullException(nameof(item));
this.decoders.Add(item);
}
///
/// Remove all decoders from the group
///
public void Clear() => this.decoders.Clear();
///
public bool CanDecode(PyType objectType, Type targetType)
=> this.decoders.Any(decoder => decoder.CanDecode(objectType, targetType));
///
public bool TryDecode(PyObject pyObj, out T? value)
{
if (pyObj is null) throw new ArgumentNullException(nameof(pyObj));
var decoder = this.GetDecoder(pyObj.GetPythonType(), typeof(T));
if (decoder is null)
{
value = default;
return false;
}
return decoder.TryDecode(pyObj, out value);
}
///
public IEnumerator GetEnumerator() => this.decoders.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => this.decoders.GetEnumerator();
public void Dispose()
{
foreach (var decoder in this.decoders.OfType())
{
decoder.Dispose();
}
this.decoders.Clear();
}
}
public static class DecoderGroupExtensions
{
///
/// Gets a concrete instance of
/// (potentially selecting one from a collection),
/// that can decode from to ,
/// or null if a matching decoder can not be found.
///
public static IPyObjectDecoder? GetDecoder(
this IPyObjectDecoder decoder,
PyType objectType, Type targetType)
{
if (decoder is null) throw new ArgumentNullException(nameof(decoder));
if (decoder is IEnumerable composite)
{
return composite
.Select(nestedDecoder => nestedDecoder.GetDecoder(objectType, targetType))
.FirstOrDefault(d => d != null);
}
return decoder.CanDecode(objectType, targetType) ? decoder : null;
}
}
}