# Path: gymnast/misc.py
# def ensure_str(val):
#     """Converts the argument to a string if it isn't one already"""
#     if isinstance(val, str):
#         return val
#     elif isinstance(val, (bytes, bytearray)):
#         return val.decode()
#     else:
#         raise ValueError('Expected bytes or string')
# 
# class MetaGettable(type):
#     """Metaclass to allow classes to be treated as dictlikes with MyClass[key].
#     Instance classes should implement a classmethod __getitem__(cls, key)."""
#     def __getitem__(cls, key):
#         return cls.__getitem__(key)


import six
from collections import namedtuple
from warnings    import warn
from ..misc      import ensure_str, MetaGettable
"""
Abstract base class for stream filters
"""

base = namedtuple('StreamFilter', ('filter_name','decoder', 'EOD', 'encoder'))
base.__new__.__defaults__ = (None, None)
class StreamFilterBase(base):
    """Stream filter class."""
    def decode(self, data, **kwargs):
        """Decode the encoded stream. Keyword arguments are the parameters from
        the stream dictionary."""
        if self.EOD:
            end = data.find(bytes(self.EOD))
            return self.decoder(data[:end if end > 0 else None], **kwargs)
        else:
            return self.decoder(data, **kwargs)
    def encode(self, data, **kwargs):
        """Encode the stream data. Keyword arguments are the parameters from
        the stream dictionary."""
        if self.encoder:
            return self.encoder(data, **kwargs) + (self.EOD if self.EOD else b'')
        else:
            warn('Encoding for {} not implemented'.format(self.filter_name))
            return data + (self.EOD if self.EOD else b'')


# Path: gymnast/misc.py
# def ensure_str(val):
#     """Converts the argument to a string if it isn't one already"""
#     if isinstance(val, str):
#         return val
#     elif isinstance(val, (bytes, bytearray)):
#         return val.decode()
#     else:
#         raise ValueError('Expected bytes or string')
# 
# class MetaGettable(type):
#     """Metaclass to allow classes to be treated as dictlikes with MyClass[key].
#     Instance classes should implement a classmethod __getitem__(cls, key)."""
#     def __getitem__(cls, key):
#         return cls.__getitem__(key)


# Path: gymnast/filters/stream_filter.py
import six
from collections import namedtuple
from warnings    import warn
from ..misc      import ensure_str, MetaGettable

"""
Abstract base class for stream filters
"""

base = namedtuple('StreamFilter', ('filter_name','decoder', 'EOD', 'encoder'))
base.__new__.__defaults__ = (None, None)
class StreamFilterBase(base):
    """Stream filter class."""
    def decode(self, data, **kwargs):
        """Decode the encoded stream. Keyword arguments are the parameters from
        the stream dictionary."""
        if self.EOD:
            end = data.find(bytes(self.EOD))
            return self.decoder(data[:end if end > 0 else None], **kwargs)
        else:
            return self.decoder(data, **kwargs)
    def encode(self, data, **kwargs):
        """Encode the stream data. Keyword arguments are the parameters from
        the stream dictionary."""
        if self.encoder:
            return self.encoder(data, **kwargs) + (self.EOD if self.EOD else b'')
        else:
            warn('Encoding for {} not implemented'.format(self.filter_name))
            return data + (self.EOD if self.EOD else b'')


@six.add_metaclass(MetaGettable)