def to_proto(
        self,
        op: cirq.Operation,
        msg: v2.program_pb2.CircuitOperation | None = None,
        *,
        constants: list[v2.program_pb2.Constant],
        raw_constants: dict[Any, int],
    ) -> v2.program_pb2.Operation:
        """Returns the stimcirq object as a proto."""
        msg = msg or v2.program_pb2.Operation()
        if getattr(op, "__module__", "").startswith(_STIMCIRQ_MODULE) or op.gate is None:
            stimcirq_obj: cirq.Operation | cirq.Gate = op
            is_gate = False
        else:
            stimcirq_obj = op.gate
            is_gate = True
        cls_name = type(stimcirq_obj).__name__
        msg.internalgate.name = cls_name
        msg.internalgate.module = _STIMCIRQ_MODULE
        gate_args = msg.internalgate.gate_args

        # Serialize arguments
        for arg_name in _STIMCIRQ_ARGS[cls_name]:
            value = getattr(stimcirq_obj, arg_name, None)
            if isinstance(value, (set, frozenset)):
                value = list(value)
            if value is not None:
                arg_to_proto(value, out=gate_args[arg_name])

        # Special handling for the pauli gate of SweepPauli
        if cls_name == "SweepPauli":
            gate_args["pauli"].arg_value.string_value = str(stimcirq_obj.pauli)  # type: ignore

        # If this is a gate (and not an Operation), add its qubits
        if is_gate:
            msg.internalgate.num_qubits = len(op.qubits)
            for qubit in op.qubits:
                if qubit not in raw_constants:
                    constants.append(
                        v2.program_pb2.Constant(
                            qubit=v2.program_pb2.Qubit(id=v2.qubit_to_proto_id(qubit))
                        )
                    )
                    raw_constants[qubit] = len(constants) - 1
                msg.qubit_constant_index.append(raw_constants[qubit])

        return msg
Returns the stimcirq object as a proto.
cirq-google/cirq_google/serialization/stimcirq_serializer.py