text: """
  
  ***************************************************
  Tutorial: Serialization and Deserialization in Syft
  ***************************************************
  
  In this file, we have the main Serializable class which orchestrates
  the serialization of objects within the Syft ecosystem. Users and
  developers of Syft need to serialize objects for a myriad of reasons,
  but the most common 3 are:
  
  - to save an object into a database which requires serialization (such as key-value dbs like Redis)
  - to send an object over the network (any protocol).
  - to save an object to disk.
  
  All serialization in Syft uses a library called 'protobuf'.
  This is a technology developed at Google for fast, secure
  serialization of objects (https://developers.google.com/protocol-buffers).
  We use an existing library like Protobuf for multiple reasons:
  
  - Protobuf creates cross-language serialization abilities
  - Protobuf is secure
  - Protobuf is fast.
  
  In short, lots of projects need serialization and so a lot of time
  and effort has gone into creating great serialization libraries. Thus,
  we want to inherit the work of others instead of having to reinvest the time
  to build these things ourselves.
  
  .. note:: DO NOT attempt to create your own serialization by
      creating strings out of objects yourself. Not only will this almost
      certainly, be slower than using technology like protobuf,
      but you will require everyone to re-implement your serialization
      techniques in every language which needs to support your object
      AND you run the risk of introducing dangerous SECURITY FLAWS.
      This is a place where we definitely want to use a robust library
      like protobuf.
  
  
  Serializing and Deserializing Syft Objects:
  ###########################################
  
  If you want to serialize an object in the syft ecosystem, the easiest way
  to do so is to just call one of the serialization methods which we install
  on the object for your convenience::
  
      import syft as sy
  
      # ObjectWithID is the simplest object in the Syft ecosystem
      # It's the parent class of many other classes. As the name
      # implies it's literally just an object with an ID.
      # We'll use it to show serialization, but you can use the
      # same approach with any serializable object in the Syft
      # ecosystem.
      from syft.core.common.object import ObjectWithID
  
      # this creates an object which has an id
      my_object = ObjectWithID()
  
      print(my_object)
      # >>> <ObjectWithID:fb1bb067-5bb7-4c49-bece-e700ab0a1514>
  
      # by default, serialize() will serialize it to a protobuf Message object
      proto_obj = serialize(my_object)
  
      print(proto_obj)
      # >>> obj_type: "syft.core.common.object.ObjectWithID"
      # >>> id {
      # >>>   obj_type: "syft.core.common.uid.UID"
      # >>>   value: "23hi23hgo2ih23ih2;o3igh;2oih;iagapwihpag"
      # >>> }
  
      # deserialization also assumes you are accepting a protobuf object
      my_object_again = sy.deserialize(blob=proto_obj)
  
      print(my_object_again)
      # >>> <ObjectWithID:fb1bb067-5bb7-4c49-bece-e700ab0a1514>
  
  However, perhaps the best thing about protobuf is that it can easily
  be turned into a wide variety of very portable representations. We have
  convenience functions for 4 popular representations: protobuf, json, binary,
  and hex. Setup::
  
      import syft as sy
      from syft.core.common.object import ObjectWithID
  
      obj = ObjectWithId()
  
  Protobuf
  ********
  
  .. code::
  
      proto_obj = serialize(obj, to_proto=True)
      proto_obj = serialize(obj, to_proto=True)
      proto_obj = serialize(obj, to_proto=True)
  
      print(proto_obj)
      # >>> obj_type: "syft.core.common.object.ObjectWithID"
      # >>> id {
      # >>>   obj_type: "syft.core.common.uid.UID"
      # >>>   value: "23hi23hgo2ih23ih2;o3igh;2oih;iagapwihpag"
      # >>> }
  
      obj_again = sy.deserialize(blob=proto_obj, from_proto=True)
  
  Binary
  ******
  
  .. code::
  
      binary_obj = serialize(obj, to_bytes=True)
      binary_obj = serialize(obj, to_bytes=True)
      binary_obj = serialize(obj, to_bytes=True)
  
      # print(binary_obj)
      # >>> b'{  "objType": "syft.core.common.object.ObjectWithID",
      # >>> "id": {    "objType": "syft.core.common.uid.UID",
      # >>> "value": "+xuwZ1u3TEm+zucAqwoVFA=="  }}'
  
      obj_again = sy.deserialize(blob=proto_obj, from_bytes=True)
  
  Now we can continue with the class definition for the Serializable class, which
  is the parent class for all serializable objects within Syft.
  
  If you'd like to see a simple example of a class which can be serialized, please read
  the source code of :py:mod:`syft.core.common.object.ObjectWithID`.
  """
  
  # syft relative
  from .deserialize import _deserialize  # noqa: F401
  from .serializable import Serializable  # noqa: F401
  from .serialize import _serialize  # noqa: F401
  