# Path: src/apscheduler/abc.py
# class Serializer(metaclass=ABCMeta):
#     __slots__ = ()
# 
#     @abstractmethod
#     def serialize(self, obj) -> bytes:
#         pass
# 
#     def serialize_to_unicode(self, obj) -> str:
#         return b64encode(self.serialize(obj)).decode('ascii')
# 
#     @abstractmethod
#     def deserialize(self, serialized: bytes):
#         pass
# 
#     def deserialize_from_unicode(self, serialized: str):
#         return self.deserialize(b64decode(serialized))
# 
# Path: src/apscheduler/marshalling.py
# def marshal_object(obj) -> tuple[str, Any]:
#     return f'{obj.__class__.__module__}:{obj.__class__.__qualname__}', obj.__getstate__()
# 
# def unmarshal_object(ref: str, state):
#     cls = callable_from_ref(ref)
#     instance = cls.__new__(cls)
#     instance.__setstate__(state)
#     return instance


from typing import Any
from cbor2 import CBOREncodeTypeError, CBORTag, dumps, loads
from ..abc import Serializer
from ..marshalling import marshal_object, unmarshal_object
import attrs
from __future__ import annotations





@attrs.define(kw_only=True, eq=False)
class CBORSerializer(Serializer):
    type_tag: int = 4664
    dump_options: dict[str, Any] = attrs.field(factory=dict)
    load_options: dict[str, Any] = attrs.field(factory=dict)

    def __attrs_post_init__(self):
        self.dump_options.setdefault('default', self._default_hook)
        self.load_options.setdefault('tag_hook', self._tag_hook)

    def _default_hook(self, encoder, value):
        if hasattr(value, '__getstate__'):
            marshalled = marshal_object(value)
            encoder.encode(CBORTag(self.type_tag, marshalled))
        else:
            raise CBOREncodeTypeError(f'cannot serialize type {value.__class__.__name__}')

    def _tag_hook(self, decoder, tag: CBORTag, shareable_index: int = None):
        if tag.tag == self.type_tag:
            cls_ref, state = tag.value

# Path: src/apscheduler/abc.py
# class Serializer(metaclass=ABCMeta):
#     __slots__ = ()
# 
#     @abstractmethod
#     def serialize(self, obj) -> bytes:
#         pass
# 
#     def serialize_to_unicode(self, obj) -> str:
#         return b64encode(self.serialize(obj)).decode('ascii')
# 
#     @abstractmethod
#     def deserialize(self, serialized: bytes):
#         pass
# 
#     def deserialize_from_unicode(self, serialized: str):
#         return self.deserialize(b64decode(serialized))
# 
# Path: src/apscheduler/marshalling.py
# def marshal_object(obj) -> tuple[str, Any]:
#     return f'{obj.__class__.__module__}:{obj.__class__.__qualname__}', obj.__getstate__()
# 
# def unmarshal_object(ref: str, state):
#     cls = callable_from_ref(ref)
#     instance = cls.__new__(cls)
#     instance.__setstate__(state)
#     return instance


# Path: src/apscheduler/serializers/cbor.py
from typing import Any
from cbor2 import CBOREncodeTypeError, CBORTag, dumps, loads
from ..abc import Serializer
from ..marshalling import marshal_object, unmarshal_object
import attrs

from __future__ import annotations





@attrs.define(kw_only=True, eq=False)
class CBORSerializer(Serializer):
    type_tag: int = 4664
    dump_options: dict[str, Any] = attrs.field(factory=dict)
    load_options: dict[str, Any] = attrs.field(factory=dict)

    def __attrs_post_init__(self):
        self.dump_options.setdefault('default', self._default_hook)
        self.load_options.setdefault('tag_hook', self._tag_hook)

    def _default_hook(self, encoder, value):
        if hasattr(value, '__getstate__'):
            marshalled = marshal_object(value)
            encoder.encode(CBORTag(self.type_tag, marshalled))
        else:
            raise CBOREncodeTypeError(f'cannot serialize type {value.__class__.__name__}')

    def _tag_hook(self, decoder, tag: CBORTag, shareable_index: int = None):
        if tag.tag == self.type_tag:
            cls_ref, state = tag.value

            return unmarshal_object(cls_ref, state)