# AUTO-GENERATED by scripts/generate_dataclasses.py — DO NOT EDIT
# Source schema: havoc_common_schema.json
#
# Regenerate with: ./scripts/generate_sdk_schema.sh

from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, Union, Tuple

from enum import Enum
class RunStatus(str, Enum):
  RUNNING = 'Running'
  PENDING = 'Pending'
  ERROR = 'Error'
  CRASHED = 'Crashed'
  FINISHED = 'Finished'

  @staticmethod
  def from_dict(obj: Any) -> 'RunStatus':
    return RunStatus(obj)

  def to_dict(self) -> str:
    return self.value

@dataclass
class RunSummary:
  status: RunStatus
  finished_at: int
  created_at: int
  worker_count: Optional[int] = None
  stop_reason: Optional[str] = None
  stop_triggered_by: Optional[str] = None

  @staticmethod
  def from_dict(obj: Any) -> 'RunSummary':
    if not isinstance(obj, dict):
      return obj
    status = RunStatus.from_dict(obj.get("status"))
    finished_at = obj.get("finished_at")
    created_at = obj.get("created_at")
    worker_count = (obj.get("worker_count")) if obj.get("worker_count") is not None else None
    stop_reason = (obj.get("stop_reason")) if obj.get("stop_reason") is not None else None
    stop_triggered_by = (obj.get("stop_triggered_by")) if obj.get("stop_triggered_by") is not None else None
    return RunSummary(status, finished_at, created_at, worker_count=worker_count, stop_reason=stop_reason, stop_triggered_by=stop_triggered_by)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.status is not None:
      result["status"] = self.status.to_dict()
    if self.finished_at is not None:
      result["finished_at"] = self.finished_at
    if self.created_at is not None:
      result["created_at"] = self.created_at
    if self.worker_count is not None:
      result["worker_count"] = self.worker_count
    if self.stop_reason is not None:
      result["stop_reason"] = self.stop_reason
    if self.stop_triggered_by is not None:
      result["stop_triggered_by"] = self.stop_triggered_by
    return result

from enum import Enum
class RcaStatus(str, Enum):
  PENDING = 'Pending'
  INPROGRESS = 'InProgress'
  COMPLETED = 'Completed'
  FAILED = 'Failed'

  @staticmethod
  def from_dict(obj: Any) -> 'RcaStatus':
    return RcaStatus(obj)

  def to_dict(self) -> str:
    return self.value

from enum import Enum
class RcaCategory(str, Enum):
  PREMATUREIRQ = 'PrematureIRQ'
  INITIALIZATIONERROR = 'InitializationError'
  UNMAPPEDMEMORYREGION = 'UnmappedMemoryRegion'
  NULLPOINTERDEREFERENCE = 'NullPointerDereference'
  OOBWRITE = 'OOBWrite'
  UNTRUSTEDCONTROLFLOWTRANSFER = 'UntrustedControlFlowTransfer'
  OOBREAD = 'OOBRead'
  STACKOVERFLOW = 'StackOverflow'
  UNDERFLOW = 'Underflow'
  OTHER = 'Other'

  @staticmethod
  def from_dict(obj: Any) -> 'RcaCategory':
    return RcaCategory(obj)

  def to_dict(self) -> str:
    return self.value

from enum import Enum
class RcaSeverity(str, Enum):
  LOW = 'Low'
  MEDIUM = 'Medium'
  HIGH = 'High'

  @staticmethod
  def from_dict(obj: Any) -> 'RcaSeverity':
    return RcaSeverity(obj)

  def to_dict(self) -> str:
    return self.value

@dataclass
class RcaReport:
  categories: List[RcaCategory]
  description: str
  severity: Optional[RcaSeverity] = None
  oracle_hash: Optional[str] = None

  @staticmethod
  def from_dict(obj: Any) -> 'RcaReport':
    if not isinstance(obj, dict):
      return obj
    categories = [RcaCategory.from_dict(it) for it in obj.get("categories", [])]
    description = obj.get("description")
    severity = (RcaSeverity.from_dict(obj.get("severity")) if obj.get("severity") is not None else None)
    oracle_hash = obj.get("oracle_hash")
    return RcaReport(categories, description, severity=severity, oracle_hash=oracle_hash)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.categories is not None:
      result["categories"] = [it.to_dict() for it in self.categories]
    if self.description is not None:
      result["description"] = self.description
    if self.severity is not None:
      result["severity"] = self.severity.to_dict()
    if self.oracle_hash is not None:
      result["oracle_hash"] = self.oracle_hash
    return result

@dataclass
class DuplicateRef:
  run_id: str
  crash_id: str

  @staticmethod
  def from_dict(obj: Any) -> 'DuplicateRef':
    if not isinstance(obj, dict):
      return obj
    run_id = obj.get("run_id")
    crash_id = obj.get("crash_id")
    return DuplicateRef(run_id, crash_id)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.run_id is not None:
      result["run_id"] = self.run_id
    if self.crash_id is not None:
      result["crash_id"] = self.crash_id
    return result

@dataclass
class CrashRcaState:
  status: RcaStatus
  rca_attempt_count: int
  report: Optional[RcaReport] = None
  error: Optional[str] = None
  duplicate_of: Optional[DuplicateRef] = None

  @staticmethod
  def from_dict(obj: Any) -> 'CrashRcaState':
    if not isinstance(obj, dict):
      return obj
    status = RcaStatus.from_dict(obj.get("status"))
    report = (RcaReport.from_dict(obj.get("report")) if obj.get("report") is not None else None)
    error = (obj.get("error")) if obj.get("error") is not None else None
    duplicate_of = (DuplicateRef.from_dict(obj.get("duplicate_of")) if obj.get("duplicate_of") is not None else None)
    rca_attempt_count = obj.get("rca_attempt_count")
    return CrashRcaState(status, rca_attempt_count, report=report, error=error, duplicate_of=duplicate_of)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.status is not None:
      result["status"] = self.status.to_dict()
    if self.report is not None:
      result["report"] = self.report.to_dict()
    if self.error is not None:
      result["error"] = self.error
    if self.duplicate_of is not None:
      result["duplicate_of"] = self.duplicate_of.to_dict()
    if self.rca_attempt_count is not None:
      result["rca_attempt_count"] = self.rca_attempt_count
    return result

@dataclass
class Crash:
  id: str
  count: int
  exit: str
  callstack: List[int] = field(default_factory=list)
  rca: Optional[CrashRcaState] = None

  @staticmethod
  def from_dict(obj: Any) -> 'Crash':
    if not isinstance(obj, dict):
      return obj
    id = obj.get("id")
    count = obj.get("count")
    exit = obj.get("exit")
    callstack = obj.get("callstack", [])
    rca = (CrashRcaState.from_dict(obj.get("rca")) if obj.get("rca") is not None else None)
    return Crash(id, count, exit, callstack=callstack, rca=rca)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.id is not None:
      result["id"] = self.id
    if self.count is not None:
      result["count"] = self.count
    if self.exit is not None:
      result["exit"] = self.exit
    if self.callstack is not None:
      result["callstack"] = self.callstack
    if self.rca is not None:
      result["rca"] = self.rca.to_dict()
    return result

@dataclass
class Hang:
  id: str
  count: int
  exit: str
  callstack: List[int] = field(default_factory=list)

  @staticmethod
  def from_dict(obj: Any) -> 'Hang':
    if not isinstance(obj, dict):
      return obj
    id = obj.get("id")
    count = obj.get("count")
    exit = obj.get("exit")
    callstack = obj.get("callstack", [])
    return Hang(id, count, exit, callstack=callstack)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.id is not None:
      result["id"] = self.id
    if self.count is not None:
      result["count"] = self.count
    if self.exit is not None:
      result["exit"] = self.exit
    if self.callstack is not None:
      result["callstack"] = self.callstack
    return result

@dataclass
class Block:
  address: int
  time_to_discover: int

  @staticmethod
  def from_dict(obj: Any) -> 'Block':
    if not isinstance(obj, dict):
      return obj
    address = obj.get("address")
    time_to_discover = obj.get("time_to_discover")
    return Block(address, time_to_discover)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.address is not None:
      result["address"] = self.address
    if self.time_to_discover is not None:
      result["time_to_discover"] = self.time_to_discover
    return result

@dataclass
class SymbolizedValue:
  value: Union[int, str]

  @staticmethod
  def from_dict(obj: Any) -> 'SymbolizedValue':
    if obj is None:
      return SymbolizedValue(None)
    if isinstance(obj, int) and not isinstance(obj, bool):
      return SymbolizedValue(obj)
    if isinstance(obj, str):
      return SymbolizedValue(obj)
    return SymbolizedValue(obj)

  def to_dict(self) -> Any:
    value = self.value
    if hasattr(value, 'to_dict'):
      return value.to_dict()
    return value

@dataclass
class DmaDescriptorPointer:
  to: DmaDescriptorField
  is_buf_end_ptr: Optional[bool] = None
  known_values: Optional[List[SymbolizedValue]] = None

  @staticmethod
  def from_dict(obj: Any) -> 'DmaDescriptorPointer':
    if not isinstance(obj, dict):
      return obj
    is_buf_end_ptr = obj.get("is_buf_end_ptr")
    known_values = [SymbolizedValue.from_dict(it) for it in obj.get("known_values", [])]
    to = DmaDescriptorField.from_dict(obj.get("to"))
    return DmaDescriptorPointer(to, is_buf_end_ptr=is_buf_end_ptr, known_values=known_values)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.is_buf_end_ptr is not None:
      result["is_buf_end_ptr"] = self.is_buf_end_ptr
    if self.known_values is not None:
      result["known_values"] = [it.to_dict() for it in self.known_values]
    if self.to is not None:
      result["to"] = self.to.to_dict()
    return result

@dataclass
class SizeRange:
  min: int
  max: int

  @staticmethod
  def from_dict(obj: Any) -> 'SizeRange':
    if not isinstance(obj, dict):
      return obj
    min = obj.get("min")
    max = obj.get("max")
    return SizeRange(min, max)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.min is not None:
      result["min"] = self.min
    if self.max is not None:
      result["max"] = self.max
    return result

@dataclass
class Buffer:
  known_sizes: Optional[Dict[str, SizeRange]] = None

  @staticmethod
  def from_dict(obj: Any) -> 'Buffer':
    if not isinstance(obj, dict):
      return obj
    known_sizes = {k: SizeRange.from_dict(v) for k, v in obj.get("known_sizes", {}).items()}
    return Buffer(known_sizes=known_sizes)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.known_sizes is not None:
      result["known_sizes"] = {k: v.to_dict() for k, v in self.known_sizes.items()}
    return result

@dataclass
class Status:
  size: int
  mask: int

  @staticmethod
  def from_dict(obj: Any) -> 'Status':
    if not isinstance(obj, dict):
      return obj
    size = obj.get("size")
    mask = obj.get("mask")
    return Status(size, mask)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.size is not None:
      result["size"] = self.size
    if self.mask is not None:
      result["mask"] = self.mask
    return result

@dataclass
class TypeDef:
  type: str

  @staticmethod
  def from_dict(obj: Any) -> 'TypeDef':
    if not isinstance(obj, dict):
      return obj
    type = obj.get("type")
    return TypeDef(type)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.type is not None:
      result["type"] = self.type
    return result

@dataclass
class DmaDescriptorFieldEntry:
  offset: int

  @staticmethod
  def from_dict(obj: Any) -> 'DmaDescriptorFieldEntry':
    if not isinstance(obj, dict):
      return obj
    offset = obj.get("offset")
    return DmaDescriptorFieldEntry(offset)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.offset is not None:
      result["offset"] = self.offset
    return result

@dataclass
class DmaDescriptor:
  fields: List[DmaDescriptorFieldEntry] = field(default_factory=list)
  typedef: Optional[str] = None

  @staticmethod
  def from_dict(obj: Any) -> 'DmaDescriptor':
    if not isinstance(obj, dict):
      return obj
    fields = [DmaDescriptorFieldEntry.from_dict(it) for it in obj.get("fields", [])]
    typedef = (obj.get("typedef")) if obj.get("typedef") is not None else None
    return DmaDescriptor(fields=fields, typedef=typedef)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.fields is not None:
      result["fields"] = [it.to_dict() for it in self.fields]
    if self.typedef is not None:
      result["typedef"] = self.typedef
    return result

@dataclass
class DmaDescriptorField:
  value: Union[DmaDescriptorPointer, DmaDescriptor, Buffer, Status, TypeDef]

  @staticmethod
  def from_dict(obj: Any) -> 'DmaDescriptorField':
    if obj is None:
      return DmaDescriptorField(None)
    if isinstance(obj, dict):
      try:
        return DmaDescriptorField(DmaDescriptorPointer.from_dict(obj))
      except:
        pass
    if isinstance(obj, dict):
      try:
        return DmaDescriptorField(DmaDescriptor.from_dict(obj))
      except:
        pass
    if isinstance(obj, dict):
      try:
        return DmaDescriptorField(Buffer.from_dict(obj))
      except:
        pass
    if isinstance(obj, dict):
      try:
        return DmaDescriptorField(Status.from_dict(obj))
      except:
        pass
    if isinstance(obj, dict):
      try:
        return DmaDescriptorField(TypeDef.from_dict(obj))
      except:
        pass
    return DmaDescriptorField(obj)

  def to_dict(self) -> Any:
    value = self.value
    if hasattr(value, 'to_dict'):
      return value.to_dict()
    return value

@dataclass
class DmaDescriptorHead:
  addr: int
  to: DmaDescriptorField
  is_buf_end_ptr: Optional[bool] = None
  known_values: Optional[List[SymbolizedValue]] = None

  @staticmethod
  def from_dict(obj: Any) -> 'DmaDescriptorHead':
    if not isinstance(obj, dict):
      return obj
    addr = obj.get("addr")
    is_buf_end_ptr = obj.get("is_buf_end_ptr")
    known_values = [SymbolizedValue.from_dict(it) for it in obj.get("known_values", [])]
    to = DmaDescriptorField.from_dict(obj.get("to"))
    return DmaDescriptorHead(addr, to, is_buf_end_ptr=is_buf_end_ptr, known_values=known_values)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.addr is not None:
      result["addr"] = self.addr
    if self.is_buf_end_ptr is not None:
      result["is_buf_end_ptr"] = self.is_buf_end_ptr
    if self.known_values is not None:
      result["known_values"] = [it.to_dict() for it in self.known_values]
    if self.to is not None:
      result["to"] = self.to.to_dict()
    return result

@dataclass
class DmaConfig:
  descriptors: List[DmaDescriptorHead] = field(default_factory=list)
  buffers: Optional[Dict[str, SizeRange]] = None

  @staticmethod
  def from_dict(obj: Any) -> 'DmaConfig':
    if not isinstance(obj, dict):
      return obj
    descriptors = [DmaDescriptorHead.from_dict(it) for it in obj.get("descriptors", [])]
    buffers = {k: SizeRange.from_dict(v) for k, v in obj.get("buffers", {}).items()}
    return DmaConfig(descriptors=descriptors, buffers=buffers)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.descriptors is not None:
      result["descriptors"] = [it.to_dict() for it in self.descriptors]
    if self.buffers is not None:
      result["buffers"] = {k: v.to_dict() for k, v in self.buffers.items()}
    return result

@dataclass
class RunStats:
  coverage: List[List[Any]]
  executions: int
  throughput: int
  crashes: List[Crash]
  hangs: List[Hang]
  new_blocks: List[Block]
  block_frequency_map: List[List[Any]]
  dma_config: DmaConfig
  code_coverage_pct: Optional[float] = None
  llm_enabled: Optional[bool] = None

  @staticmethod
  def from_dict(obj: Any) -> 'RunStats':
    if not isinstance(obj, dict):
      return obj
    coverage = [tuple(it) for it in obj.get("coverage", [])]
    executions = obj.get("executions")
    throughput = obj.get("throughput")
    crashes = [Crash.from_dict(it) for it in obj.get("crashes", [])]
    hangs = [Hang.from_dict(it) for it in obj.get("hangs", [])]
    new_blocks = [Block.from_dict(it) for it in obj.get("new_blocks", [])]
    block_frequency_map = [tuple(it) for it in obj.get("block_frequency_map", [])]
    dma_config = DmaConfig.from_dict(obj.get("dma_config"))
    code_coverage_pct = (obj.get("code_coverage_pct")) if obj.get("code_coverage_pct") is not None else None
    llm_enabled = obj.get("llm_enabled")
    return RunStats(coverage, executions, throughput, crashes, hangs, new_blocks, block_frequency_map, dma_config, code_coverage_pct=code_coverage_pct, llm_enabled=llm_enabled)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.coverage is not None:
      result["coverage"] = [list(it) for it in self.coverage]
    if self.executions is not None:
      result["executions"] = self.executions
    if self.throughput is not None:
      result["throughput"] = self.throughput
    if self.crashes is not None:
      result["crashes"] = [it.to_dict() for it in self.crashes]
    if self.hangs is not None:
      result["hangs"] = [it.to_dict() for it in self.hangs]
    if self.new_blocks is not None:
      result["new_blocks"] = [it.to_dict() for it in self.new_blocks]
    if self.block_frequency_map is not None:
      result["block_frequency_map"] = [list(it) for it in self.block_frequency_map]
    if self.dma_config is not None:
      result["dma_config"] = self.dma_config.to_dict()
    if self.code_coverage_pct is not None:
      result["code_coverage_pct"] = self.code_coverage_pct
    if self.llm_enabled is not None:
      result["llm_enabled"] = self.llm_enabled
    return result

from enum import Enum
class MemoryType(str, Enum):
  RAM = 'ram'
  ROM = 'rom'
  MMIO = 'mmio'
  IO_OVERLAY = 'io_overlay'

  @staticmethod
  def from_dict(obj: Any) -> 'MemoryType':
    return MemoryType(obj)

  def to_dict(self) -> str:
    return self.value

@dataclass
class MemoryFileSegment:
  memory_offset: int
  file_offset: int
  size: int

  @staticmethod
  def from_dict(obj: Any) -> 'MemoryFileSegment':
    if not isinstance(obj, dict):
      return obj
    memory_offset = obj.get("memory_offset")
    file_offset = obj.get("file_offset")
    size = obj.get("size")
    return MemoryFileSegment(memory_offset, file_offset, size)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.memory_offset is not None:
      result["memory_offset"] = self.memory_offset
    if self.file_offset is not None:
      result["file_offset"] = self.file_offset
    if self.size is not None:
      result["size"] = self.size
    return result

@dataclass
class MemoryFile:
  segments: List[MemoryFileSegment]
  file_id: str

  @staticmethod
  def from_dict(obj: Any) -> 'MemoryFile':
    if not isinstance(obj, dict):
      return obj
    segments = [MemoryFileSegment.from_dict(it) for it in obj.get("segments", [])]
    file_id = obj.get("file_id")
    return MemoryFile(segments, file_id)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.segments is not None:
      result["segments"] = [it.to_dict() for it in self.segments]
    if self.file_id is not None:
      result["file_id"] = self.file_id
    return result

@dataclass
class Memory:
  base_addr: int
  memory_type: MemoryType
  size: int
  file: Optional[MemoryFile] = None
  fill: Optional[int] = None
  aliased_to: Optional[int] = None
  executable: Optional[bool] = None

  @staticmethod
  def from_dict(obj: Any) -> 'Memory':
    if not isinstance(obj, dict):
      return obj
    base_addr = obj.get("base_addr")
    memory_type = MemoryType.from_dict(obj.get("memory_type"))
    size = obj.get("size")
    file = (MemoryFile.from_dict(obj.get("file")) if obj.get("file") is not None else None)
    fill = (obj.get("fill")) if obj.get("fill") is not None else None
    aliased_to = (obj.get("aliased_to")) if obj.get("aliased_to") is not None else None
    executable = (obj.get("executable")) if obj.get("executable") is not None else None
    return Memory(base_addr, memory_type, size, file=file, fill=fill, aliased_to=aliased_to, executable=executable)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.base_addr is not None:
      result["base_addr"] = self.base_addr
    if self.memory_type is not None:
      result["memory_type"] = self.memory_type.to_dict()
    if self.size is not None:
      result["size"] = self.size
    if self.file is not None:
      result["file"] = self.file.to_dict()
    if self.fill is not None:
      result["fill"] = self.fill
    if self.aliased_to is not None:
      result["aliased_to"] = self.aliased_to
    if self.executable is not None:
      result["executable"] = self.executable
    return result

@dataclass
class Nvic:
  num_vecs: Optional[int] = None
  interrupt_limit: Optional[int] = None
  disabled_irqs: Optional[List[int]] = None
  enabled_irqs: Optional[List[Any]] = None
  enable_nested_interrupts: Optional[bool] = None
  allow_active_interrupt_pending: Optional[bool] = None

  @staticmethod
  def from_dict(obj: Any) -> 'Nvic':
    if not isinstance(obj, dict):
      return obj
    num_vecs = obj.get("num_vecs")
    interrupt_limit = obj.get("interrupt_limit")
    disabled_irqs = obj.get("disabled_irqs", [])
    enabled_irqs = (obj.get("enabled_irqs", [])) if obj.get("enabled_irqs") is not None else None
    enable_nested_interrupts = obj.get("enable_nested_interrupts")
    allow_active_interrupt_pending = obj.get("allow_active_interrupt_pending")
    return Nvic(num_vecs=num_vecs, interrupt_limit=interrupt_limit, disabled_irqs=disabled_irqs, enabled_irqs=enabled_irqs, enable_nested_interrupts=enable_nested_interrupts, allow_active_interrupt_pending=allow_active_interrupt_pending)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.num_vecs is not None:
      result["num_vecs"] = self.num_vecs
    if self.interrupt_limit is not None:
      result["interrupt_limit"] = self.interrupt_limit
    if self.disabled_irqs is not None:
      result["disabled_irqs"] = self.disabled_irqs
    if self.enabled_irqs is not None:
      result["enabled_irqs"] = self.enabled_irqs
    if self.enable_nested_interrupts is not None:
      result["enable_nested_interrupts"] = self.enable_nested_interrupts
    if self.allow_active_interrupt_pending is not None:
      result["allow_active_interrupt_pending"] = self.allow_active_interrupt_pending
    return result

@dataclass
class CortexMGeneric:
  memory_map: Optional[Dict[str, Memory]] = None
  nvic: Optional[Nvic] = None

  @staticmethod
  def from_dict(obj: Any) -> 'CortexMGeneric':
    if not isinstance(obj, dict):
      return obj
    memory_map = {k: Memory.from_dict(v) for k, v in obj.get("memory_map", {}).items()}
    nvic = (Nvic.from_dict(obj.get("nvic")) if obj.get("nvic") is not None else None)
    return CortexMGeneric(memory_map=memory_map, nvic=nvic)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.memory_map is not None:
      result["memory_map"] = {k: v.to_dict() for k, v in self.memory_map.items()}
    if self.nvic is not None:
      result["nvic"] = self.nvic.to_dict()
    return result

@dataclass
class STM32F4:
  memory_map: Optional[Dict[str, Memory]] = None
  uart_data_addresses: Optional[List[int]] = None
  nvic: Optional[Nvic] = None

  @staticmethod
  def from_dict(obj: Any) -> 'STM32F4':
    if not isinstance(obj, dict):
      return obj
    memory_map = {k: Memory.from_dict(v) for k, v in obj.get("memory_map", {}).items()}
    uart_data_addresses = obj.get("uart_data_addresses", [])
    nvic = (Nvic.from_dict(obj.get("nvic")) if obj.get("nvic") is not None else None)
    return STM32F4(memory_map=memory_map, uart_data_addresses=uart_data_addresses, nvic=nvic)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.memory_map is not None:
      result["memory_map"] = {k: v.to_dict() for k, v in self.memory_map.items()}
    if self.uart_data_addresses is not None:
      result["uart_data_addresses"] = self.uart_data_addresses
    if self.nvic is not None:
      result["nvic"] = self.nvic.to_dict()
    return result

@dataclass
class Interrupt:
  isr: str
  enable: List[Any] = field(default_factory=list)
  flag: List[Any] = field(default_factory=list)

  @staticmethod
  def from_dict(obj: Any) -> 'Interrupt':
    if not isinstance(obj, dict):
      return obj
    isr = obj.get("isr")
    enable = obj.get("enable", [])
    flag = obj.get("flag", [])
    return Interrupt(isr, enable=enable, flag=flag)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.isr is not None:
      result["isr"] = self.isr
    if self.enable is not None:
      result["enable"] = self.enable
    if self.flag is not None:
      result["flag"] = self.flag
    return result

@dataclass
class TI_CC430F6137:
  memory_map: Optional[Dict[str, Memory]] = None
  interrupts: Optional[Dict[str, Interrupt]] = None
  symbols: Optional[Dict[str, int]] = None

  @staticmethod
  def from_dict(obj: Any) -> 'TI_CC430F6137':
    if not isinstance(obj, dict):
      return obj
    memory_map = {k: Memory.from_dict(v) for k, v in obj.get("memory_map", {}).items()}
    interrupts = {k: Interrupt.from_dict(v) for k, v in obj.get("interrupts", {}).items()}
    symbols = obj.get("symbols", {})
    return TI_CC430F6137(memory_map=memory_map, interrupts=interrupts, symbols=symbols)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.memory_map is not None:
      result["memory_map"] = {k: v.to_dict() for k, v in self.memory_map.items()}
    if self.interrupts is not None:
      result["interrupts"] = {k: v.to_dict() for k, v in self.interrupts.items()}
    if self.symbols is not None:
      result["symbols"] = self.symbols
    return result

@dataclass
class ESP32S3:
  memory_map: Optional[Dict[str, Memory]] = None

  @staticmethod
  def from_dict(obj: Any) -> 'ESP32S3':
    if not isinstance(obj, dict):
      return obj
    memory_map = {k: Memory.from_dict(v) for k, v in obj.get("memory_map", {}).items()}
    return ESP32S3(memory_map=memory_map)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.memory_map is not None:
      result["memory_map"] = {k: v.to_dict() for k, v in self.memory_map.items()}
    return result

@dataclass
class Mcu:
  CortexMGeneric: Optional[CortexMGeneric] = None
  STM32_STM32F4: Optional[STM32F4] = None
  TI_CC430F6137: Optional[TI_CC430F6137] = None
  ESP32S3: Optional[ESP32S3] = None

  @staticmethod
  def from_dict(obj: Any) -> 'Mcu':
    if not isinstance(obj, dict):
      return obj  # type: ignore
    if "CortexMGeneric" in obj:
      return Mcu(CortexMGeneric=CortexMGeneric.from_dict(obj['CortexMGeneric']))
    if "STM32_STM32F4" in obj:
      return Mcu(STM32_STM32F4=STM32F4.from_dict(obj['STM32_STM32F4']))
    if "TI_CC430F6137" in obj:
      return Mcu(TI_CC430F6137=TI_CC430F6137.from_dict(obj['TI_CC430F6137']))
    if "ESP32S3" in obj:
      return Mcu(ESP32S3=ESP32S3.from_dict(obj['ESP32S3']))
    return Mcu()

  def to_dict(self) -> dict:
    # emit only the set variant
    if self.CortexMGeneric is not None:
      return {"CortexMGeneric": self.CortexMGeneric.to_dict()}
    if self.STM32_STM32F4 is not None:
      return {"STM32_STM32F4": self.STM32_STM32F4.to_dict()}
    if self.TI_CC430F6137 is not None:
      return {"TI_CC430F6137": self.TI_CC430F6137.to_dict()}
    if self.ESP32S3 is not None:
      return {"ESP32S3": self.ESP32S3.to_dict()}
    return {}

from enum import Enum
class TickKind(str, Enum):
  FUZZED = 'fuzzed'

  @staticmethod
  def from_dict(obj: Any) -> 'TickKind':
    return TickKind(obj)

  def to_dict(self) -> str:
    return self.value

@dataclass
class Tick:
  value: Union[TickKind, int]

  @staticmethod
  def from_dict(obj: Any) -> 'Tick':
    if obj is None:
      return Tick(None)
    if isinstance(obj, str):
      try:
        return Tick(TickKind.from_dict(obj))
      except:
        pass
    if isinstance(obj, int) and not isinstance(obj, bool):
      return Tick(obj)
    return Tick(obj)

  def to_dict(self) -> Any:
    value = self.value
    if hasattr(value, 'to_dict'):
      return value.to_dict()
    return value

@dataclass
class TriggerMode:
  addr: Optional[Any] = None
  every_nth_tick: Optional[Tick] = None

  @staticmethod
  def from_dict(obj: Any) -> 'TriggerMode':
    if not isinstance(obj, dict):
      return obj  # type: ignore
    if "addr" in obj:
      return TriggerMode(addr=obj['addr'])
    if "every_nth_tick" in obj:
      return TriggerMode(every_nth_tick=Tick.from_dict(obj['every_nth_tick']))
    return TriggerMode()

  def to_dict(self) -> dict:
    # emit only the set variant
    if self.addr is not None:
      return {"addr": self.addr}
    if self.every_nth_tick is not None:
      return {"every_nth_tick": self.every_nth_tick.to_dict()}
    return {}

from enum import Enum
class FuzzMode(str, Enum):
  FUZZED = 'fuzzed'
  ROUND_ROBIN = 'round_robin'

  @staticmethod
  def from_dict(obj: Any) -> 'FuzzMode':
    return FuzzMode(obj)

  def to_dict(self) -> str:
    return self.value

@dataclass
class TriggerKind:
  Fixed: Optional[Any] = None
  Dynamic: Optional[Any] = None

  @staticmethod
  def from_dict(obj: Any) -> 'TriggerKind':
    if not isinstance(obj, dict):
      return obj  # type: ignore
    if "Fixed" in obj:
      return TriggerKind(Fixed=obj['Fixed'])
    if "Dynamic" in obj:
      return TriggerKind(Dynamic=obj['Dynamic'])
    return TriggerKind()

  def to_dict(self) -> dict:
    # emit only the set variant
    if self.Fixed is not None:
      return {"Fixed": self.Fixed}
    if self.Dynamic is not None:
      return {"Dynamic": self.Dynamic}
    return {}

@dataclass
class Trigger:
  mode: TriggerMode
  kind: TriggerKind

  @staticmethod
  def from_dict(obj: Any) -> 'Trigger':
    if not isinstance(obj, dict):
      return obj
    mode = TriggerMode.from_dict(obj.get("mode"))
    kind = TriggerKind.from_dict(obj.get("kind"))
    return Trigger(mode, kind)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.mode is not None:
      result["mode"] = self.mode.to_dict()
    if self.kind is not None:
      result["kind"] = self.kind.to_dict()
    return result

@dataclass
class Bitextract:
  access_size: int
  addr: int
  left_shift: int
  mask: int
  pc: int
  size: int

  @staticmethod
  def from_dict(obj: Any) -> 'Bitextract':
    if not isinstance(obj, dict):
      return obj
    access_size = obj.get("access_size")
    addr = obj.get("addr")
    left_shift = obj.get("left_shift")
    mask = obj.get("mask")
    pc = obj.get("pc")
    size = obj.get("size")
    return Bitextract(access_size, addr, left_shift, mask, pc, size)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.access_size is not None:
      result["access_size"] = self.access_size
    if self.addr is not None:
      result["addr"] = self.addr
    if self.left_shift is not None:
      result["left_shift"] = self.left_shift
    if self.mask is not None:
      result["mask"] = self.mask
    if self.pc is not None:
      result["pc"] = self.pc
    if self.size is not None:
      result["size"] = self.size
    return result

@dataclass
class Constant:
  access_size: int
  addr: int
  pc: int
  val: int

  @staticmethod
  def from_dict(obj: Any) -> 'Constant':
    if not isinstance(obj, dict):
      return obj
    access_size = obj.get("access_size")
    addr = obj.get("addr")
    pc = obj.get("pc")
    val = obj.get("val")
    return Constant(access_size, addr, pc, val)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.access_size is not None:
      result["access_size"] = self.access_size
    if self.addr is not None:
      result["addr"] = self.addr
    if self.pc is not None:
      result["pc"] = self.pc
    if self.val is not None:
      result["val"] = self.val
    return result

@dataclass
class Passthrough:
  addr: int
  pc: int
  access_size: Optional[int] = None
  init_val: Optional[int] = None

  @staticmethod
  def from_dict(obj: Any) -> 'Passthrough':
    if not isinstance(obj, dict):
      return obj
    access_size = obj.get("access_size")
    addr = obj.get("addr")
    pc = obj.get("pc")
    init_val = obj.get("init_val")
    return Passthrough(addr, pc, access_size=access_size, init_val=init_val)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.access_size is not None:
      result["access_size"] = self.access_size
    if self.addr is not None:
      result["addr"] = self.addr
    if self.pc is not None:
      result["pc"] = self.pc
    if self.init_val is not None:
      result["init_val"] = self.init_val
    return result

@dataclass
class Set:
  addr: int
  pc: int
  vals: List[int] = field(default_factory=list)
  access_size: Optional[int] = None

  @staticmethod
  def from_dict(obj: Any) -> 'Set':
    if not isinstance(obj, dict):
      return obj
    access_size = obj.get("access_size")
    addr = obj.get("addr")
    pc = obj.get("pc")
    vals = obj.get("vals", [])
    return Set(addr, pc, vals=vals, access_size=access_size)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.access_size is not None:
      result["access_size"] = self.access_size
    if self.addr is not None:
      result["addr"] = self.addr
    if self.pc is not None:
      result["pc"] = self.pc
    if self.vals is not None:
      result["vals"] = self.vals
    return result

@dataclass
class Unmodeled:
  addr: int
  pc: int
  access_size: Optional[int] = None

  @staticmethod
  def from_dict(obj: Any) -> 'Unmodeled':
    if not isinstance(obj, dict):
      return obj
    access_size = obj.get("access_size")
    addr = obj.get("addr")
    pc = obj.get("pc")
    return Unmodeled(addr, pc, access_size=access_size)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.access_size is not None:
      result["access_size"] = self.access_size
    if self.addr is not None:
      result["addr"] = self.addr
    if self.pc is not None:
      result["pc"] = self.pc
    return result

@dataclass
class MmioModels:
  bitextract: Optional[Dict[str, Bitextract]] = None
  constant: Optional[Dict[str, Constant]] = None
  passthrough: Optional[Dict[str, Passthrough]] = None
  set: Optional[Dict[str, Set]] = None
  unmodeled: Optional[Dict[str, Unmodeled]] = None

  @staticmethod
  def from_dict(obj: Any) -> 'MmioModels':
    if not isinstance(obj, dict):
      return obj
    bitextract = {k: Bitextract.from_dict(v) for k, v in obj.get("bitextract", {}).items()}
    constant = {k: Constant.from_dict(v) for k, v in obj.get("constant", {}).items()}
    passthrough = {k: Passthrough.from_dict(v) for k, v in obj.get("passthrough", {}).items()}
    set = {k: Set.from_dict(v) for k, v in obj.get("set", {}).items()}
    unmodeled = {k: Unmodeled.from_dict(v) for k, v in obj.get("unmodeled", {}).items()}
    return MmioModels(bitextract=bitextract, constant=constant, passthrough=passthrough, set=set, unmodeled=unmodeled)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.bitextract is not None:
      result["bitextract"] = {k: v.to_dict() for k, v in self.bitextract.items()}
    if self.constant is not None:
      result["constant"] = {k: v.to_dict() for k, v in self.constant.items()}
    if self.passthrough is not None:
      result["passthrough"] = {k: v.to_dict() for k, v in self.passthrough.items()}
    if self.set is not None:
      result["set"] = {k: v.to_dict() for k, v in self.set.items()}
    if self.unmodeled is not None:
      result["unmodeled"] = {k: v.to_dict() for k, v in self.unmodeled.items()}
    return result

@dataclass
class FuzzerConfig:
  interrupt_interval: int
  fuzz_consumption_timeout: int
  global_timer_scale: Optional[int] = None
  instr_limit: Optional[int] = None
  interrupt_triggers: Optional[Dict[str, Trigger]] = None
  use_access_contexts: Optional[bool] = None
  use_skip_irq_magic_byte: Optional[bool] = None
  mmio_models: Optional[MmioModels] = None

  @staticmethod
  def from_dict(obj: Any) -> 'FuzzerConfig':
    if not isinstance(obj, dict):
      return obj
    interrupt_interval = obj.get("interrupt_interval")
    fuzz_consumption_timeout = obj.get("fuzz_consumption_timeout")
    global_timer_scale = obj.get("global_timer_scale")
    instr_limit = obj.get("instr_limit")
    interrupt_triggers = {k: Trigger.from_dict(v) for k, v in obj.get("interrupt_triggers", {}).items()}
    use_access_contexts = obj.get("use_access_contexts")
    use_skip_irq_magic_byte = obj.get("use_skip_irq_magic_byte")
    mmio_models = MmioModels.from_dict(obj.get("mmio_models"))
    return FuzzerConfig(interrupt_interval, fuzz_consumption_timeout, global_timer_scale=global_timer_scale, instr_limit=instr_limit, interrupt_triggers=interrupt_triggers, use_access_contexts=use_access_contexts, use_skip_irq_magic_byte=use_skip_irq_magic_byte, mmio_models=mmio_models)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.interrupt_interval is not None:
      result["interrupt_interval"] = self.interrupt_interval
    if self.fuzz_consumption_timeout is not None:
      result["fuzz_consumption_timeout"] = self.fuzz_consumption_timeout
    if self.global_timer_scale is not None:
      result["global_timer_scale"] = self.global_timer_scale
    if self.instr_limit is not None:
      result["instr_limit"] = self.instr_limit
    if self.interrupt_triggers is not None:
      result["interrupt_triggers"] = {k: v.to_dict() for k, v in self.interrupt_triggers.items()}
    if self.use_access_contexts is not None:
      result["use_access_contexts"] = self.use_access_contexts
    if self.use_skip_irq_magic_byte is not None:
      result["use_skip_irq_magic_byte"] = self.use_skip_irq_magic_byte
    if self.mmio_models is not None:
      result["mmio_models"] = self.mmio_models.to_dict()
    return result

@dataclass
class Testcase:
  input_id: str
  exit_reason: str
  exit_pc: int
  num_blocks: int
  timestamp: str

  @staticmethod
  def from_dict(obj: Any) -> 'Testcase':
    if not isinstance(obj, dict):
      return obj
    input_id = obj.get("input_id")
    exit_reason = obj.get("exit_reason")
    exit_pc = obj.get("exit_pc")
    num_blocks = obj.get("num_blocks")
    timestamp = obj.get("timestamp")
    return Testcase(input_id, exit_reason, exit_pc, num_blocks, timestamp)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.input_id is not None:
      result["input_id"] = self.input_id
    if self.exit_reason is not None:
      result["exit_reason"] = self.exit_reason
    if self.exit_pc is not None:
      result["exit_pc"] = self.exit_pc
    if self.num_blocks is not None:
      result["num_blocks"] = self.num_blocks
    if self.timestamp is not None:
      result["timestamp"] = self.timestamp
    return result

@dataclass
class UploadImageRequest:
  payload: List[int]
  label: str

  @staticmethod
  def from_dict(obj: Any) -> 'UploadImageRequest':
    if not isinstance(obj, dict):
      return obj
    payload = obj.get("payload", [])
    label = obj.get("label")
    return UploadImageRequest(payload, label)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.payload is not None:
      result["payload"] = self.payload
    if self.label is not None:
      result["label"] = self.label
    return result

@dataclass
class InferConfigRequest:
  file_id: str
  mcu: str

  @staticmethod
  def from_dict(obj: Any) -> 'InferConfigRequest':
    if not isinstance(obj, dict):
      return obj
    file_id = obj.get("file_id")
    mcu = obj.get("mcu")
    return InferConfigRequest(file_id, mcu)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.file_id is not None:
      result["file_id"] = self.file_id
    if self.mcu is not None:
      result["mcu"] = self.mcu
    return result

@dataclass
class RawImageSegment:
  address: int
  file_id: str
  file_offset: int

  @staticmethod
  def from_dict(obj: Any) -> 'RawImageSegment':
    if not isinstance(obj, dict):
      return obj
    address = obj.get("address")
    file_id = obj.get("file_id")
    file_offset = obj.get("file_offset")
    return RawImageSegment(address, file_id, file_offset)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.address is not None:
      result["address"] = self.address
    if self.file_id is not None:
      result["file_id"] = self.file_id
    if self.file_offset is not None:
      result["file_offset"] = self.file_offset
    return result

@dataclass
class RawImage:
  segments: List[RawImageSegment] = field(default_factory=list)

  @staticmethod
  def from_dict(obj: Any) -> 'RawImage':
    if not isinstance(obj, dict):
      return obj
    segments = [RawImageSegment.from_dict(it) for it in obj.get("segments", [])]
    return RawImage(segments=segments)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.segments is not None:
      result["segments"] = [it.to_dict() for it in self.segments]
    return result

@dataclass
class ImageFormat:
  Elf: Optional[Any] = None
  Raw: Optional[RawImage] = None

  @staticmethod
  def from_dict(obj: Any) -> 'ImageFormat':
    if not isinstance(obj, dict):
      return obj  # type: ignore
    if "Elf" in obj:
      return ImageFormat(Elf=obj['Elf'])
    if "Raw" in obj:
      return ImageFormat(Raw=RawImage.from_dict(obj['Raw']))
    return ImageFormat()

  def to_dict(self) -> dict:
    # emit only the set variant
    if self.Elf is not None:
      return {"Elf": self.Elf}
    if self.Raw is not None:
      return {"Raw": self.Raw.to_dict()}
    return {}

@dataclass
class DmaBuffer:
  addr: int
  size: int

  @staticmethod
  def from_dict(obj: Any) -> 'DmaBuffer':
    if not isinstance(obj, dict):
      return obj
    addr = obj.get("addr")
    size = obj.get("size")
    return DmaBuffer(addr, size)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.addr is not None:
      result["addr"] = self.addr
    if self.size is not None:
      result["size"] = self.size
    return result

from enum import Enum
class PatchType(str, Enum):
  RETURN = 'Return'
  RETURN0 = 'Return0'
  RETURN1 = 'Return1'
  NOP = 'Nop'

  @staticmethod
  def from_dict(obj: Any) -> 'PatchType':
    return PatchType(obj)

  def to_dict(self) -> str:
    return self.value

@dataclass
class Patch:
  address: int
  patch_type: PatchType

  @staticmethod
  def from_dict(obj: Any) -> 'Patch':
    if not isinstance(obj, dict):
      return obj
    address = obj.get("address")
    patch_type = PatchType.from_dict(obj.get("patch_type"))
    return Patch(address, patch_type)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.address is not None:
      result["address"] = self.address
    if self.patch_type is not None:
      result["patch_type"] = self.patch_type.to_dict()
    return result

@dataclass
class Handler:
  address: int
  action: str

  @staticmethod
  def from_dict(obj: Any) -> 'Handler':
    if not isinstance(obj, dict):
      return obj
    address = obj.get("address")
    action = obj.get("action")
    return Handler(address, action)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.address is not None:
      result["address"] = self.address
    if self.action is not None:
      result["action"] = self.action
    return result

@dataclass
class Image:
  image_format: ImageFormat
  entry_address: int
  dma_buffers: List[DmaBuffer] = field(default_factory=list)
  patches: List[Patch] = field(default_factory=list)
  symbols: List[List[Any]] = field(default_factory=list)
  handlers: List[Handler] = field(default_factory=list)
  timestamp: Optional[int] = None
  name: Optional[str] = None
  function_addresses: Optional[List[int]] = None

  @staticmethod
  def from_dict(obj: Any) -> 'Image':
    if not isinstance(obj, dict):
      return obj
    image_format = ImageFormat.from_dict(obj.get("image_format"))
    entry_address = obj.get("entry_address")
    dma_buffers = [DmaBuffer.from_dict(it) for it in obj.get("dma_buffers", [])]
    patches = [Patch.from_dict(it) for it in obj.get("patches", [])]
    symbols = [tuple(it) for it in obj.get("symbols", [])]
    handlers = [Handler.from_dict(it) for it in obj.get("handlers", [])]
    timestamp = (obj.get("timestamp")) if obj.get("timestamp") is not None else None
    name = obj.get("name")
    function_addresses = obj.get("function_addresses", [])
    return Image(image_format, entry_address, dma_buffers=dma_buffers, patches=patches, symbols=symbols, handlers=handlers, timestamp=timestamp, name=name, function_addresses=function_addresses)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.image_format is not None:
      result["image_format"] = self.image_format.to_dict()
    if self.entry_address is not None:
      result["entry_address"] = self.entry_address
    if self.dma_buffers is not None:
      result["dma_buffers"] = [it.to_dict() for it in self.dma_buffers]
    if self.patches is not None:
      result["patches"] = [it.to_dict() for it in self.patches]
    if self.symbols is not None:
      result["symbols"] = [list(it) for it in self.symbols]
    if self.handlers is not None:
      result["handlers"] = [it.to_dict() for it in self.handlers]
    if self.timestamp is not None:
      result["timestamp"] = self.timestamp
    if self.name is not None:
      result["name"] = self.name
    if self.function_addresses is not None:
      result["function_addresses"] = self.function_addresses
    return result

@dataclass
class CreatorInfo:
  created_by: Optional[str] = None
  created_by_api_key: Optional[bool] = None

  @staticmethod
  def from_dict(obj: Any) -> 'CreatorInfo':
    if not isinstance(obj, dict):
      return obj
    created_by = (obj.get("created_by")) if obj.get("created_by") is not None else None
    created_by_api_key = obj.get("created_by_api_key")
    return CreatorInfo(created_by=created_by, created_by_api_key=created_by_api_key)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.created_by is not None:
      result["created_by"] = self.created_by
    if self.created_by_api_key is not None:
      result["created_by_api_key"] = self.created_by_api_key
    return result

@dataclass
class CreateAnalysisRequest:
  mcu: Mcu
  image: Image
  auto: Optional[bool] = None
  worker_count: Optional[int] = None
  timeout_secs: Optional[int] = None
  creator: Optional[CreatorInfo] = None
  tags: Optional[List[str]] = None

  @staticmethod
  def from_dict(obj: Any) -> 'CreateAnalysisRequest':
    if not isinstance(obj, dict):
      return obj
    mcu = Mcu.from_dict(obj.get("mcu"))
    image = Image.from_dict(obj.get("image"))
    auto = obj.get("auto")
    worker_count = (obj.get("worker_count")) if obj.get("worker_count") is not None else None
    timeout_secs = (obj.get("timeout_secs")) if obj.get("timeout_secs") is not None else None
    creator = CreatorInfo.from_dict(obj.get("creator"))
    tags = obj.get("tags", [])
    return CreateAnalysisRequest(mcu, image, auto=auto, worker_count=worker_count, timeout_secs=timeout_secs, creator=creator, tags=tags)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.mcu is not None:
      result["mcu"] = self.mcu.to_dict()
    if self.image is not None:
      result["image"] = self.image.to_dict()
    if self.auto is not None:
      result["auto"] = self.auto
    if self.worker_count is not None:
      result["worker_count"] = self.worker_count
    if self.timeout_secs is not None:
      result["timeout_secs"] = self.timeout_secs
    if self.creator is not None:
      result["creator"] = self.creator.to_dict()
    if self.tags is not None:
      result["tags"] = self.tags
    return result

@dataclass
class RunParams:
  worker_count: int
  dry_run: bool

  @staticmethod
  def from_dict(obj: Any) -> 'RunParams':
    if not isinstance(obj, dict):
      return obj
    worker_count = obj.get("worker_count")
    dry_run = obj.get("dry_run")
    return RunParams(worker_count, dry_run)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.worker_count is not None:
      result["worker_count"] = self.worker_count
    if self.dry_run is not None:
      result["dry_run"] = self.dry_run
    return result

@dataclass
class RunConfig:
  mcu: Mcu
  worker_count: int
  dry_run: bool
  image: Image
  fuzzer_config: FuzzerConfig
  analysis_id: Optional[str] = None
  dma_config: Optional[DmaConfig] = None

  @staticmethod
  def from_dict(obj: Any) -> 'RunConfig':
    if not isinstance(obj, dict):
      return obj
    mcu = Mcu.from_dict(obj.get("mcu"))
    worker_count = obj.get("worker_count")
    dry_run = obj.get("dry_run")
    image = Image.from_dict(obj.get("image"))
    fuzzer_config = FuzzerConfig.from_dict(obj.get("fuzzer_config"))
    analysis_id = obj.get("analysis_id")
    dma_config = (DmaConfig.from_dict(obj.get("dma_config")) if obj.get("dma_config") is not None else None)
    return RunConfig(mcu, worker_count, dry_run, image, fuzzer_config, analysis_id=analysis_id, dma_config=dma_config)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.mcu is not None:
      result["mcu"] = self.mcu.to_dict()
    if self.worker_count is not None:
      result["worker_count"] = self.worker_count
    if self.dry_run is not None:
      result["dry_run"] = self.dry_run
    if self.image is not None:
      result["image"] = self.image.to_dict()
    if self.fuzzer_config is not None:
      result["fuzzer_config"] = self.fuzzer_config.to_dict()
    if self.analysis_id is not None:
      result["analysis_id"] = self.analysis_id
    if self.dma_config is not None:
      result["dma_config"] = self.dma_config.to_dict()
    return result

@dataclass
class FileMetadata:
  id: str
  size: int
  is_elf: bool

  @staticmethod
  def from_dict(obj: Any) -> 'FileMetadata':
    if not isinstance(obj, dict):
      return obj
    id = obj.get("id")
    size = obj.get("size")
    is_elf = obj.get("is_elf")
    return FileMetadata(id, size, is_elf)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.id is not None:
      result["id"] = self.id
    if self.size is not None:
      result["size"] = self.size
    if self.is_elf is not None:
      result["is_elf"] = self.is_elf
    return result

@dataclass
class InferredConfig:
  memory_map: Dict[str, Memory]
  image: Image

  @staticmethod
  def from_dict(obj: Any) -> 'InferredConfig':
    if not isinstance(obj, dict):
      return obj
    memory_map = {k: Memory.from_dict(v) for k, v in obj.get("memory_map", {}).items()}
    image = Image.from_dict(obj.get("image"))
    return InferredConfig(memory_map, image)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.memory_map is not None:
      result["memory_map"] = {k: v.to_dict() for k, v in self.memory_map.items()}
    if self.image is not None:
      result["image"] = self.image.to_dict()
    return result

@dataclass
class DebugSessionId:
  run_id: str
  testcase_id: str

  @staticmethod
  def from_dict(obj: Any) -> 'DebugSessionId':
    if not isinstance(obj, dict):
      return obj
    run_id = obj.get("run_id")
    testcase_id = obj.get("testcase_id")
    return DebugSessionId(run_id, testcase_id)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.run_id is not None:
      result["run_id"] = self.run_id
    if self.testcase_id is not None:
      result["testcase_id"] = self.testcase_id
    return result

from enum import Enum
class AnalysisStage(str, Enum):
  MANUAL = 'Manual'
  INFERCONFIG = 'InferConfig'
  DRYRUN = 'DryRun'
  FUZZING = 'Fuzzing'
  RECONFIGURE = 'Reconfigure'
  INTERVENTION = 'Intervention'
  STOPPED = 'Stopped'
  COMPLETED = 'Completed'
  FAILED = 'Failed'

  @staticmethod
  def from_dict(obj: Any) -> 'AnalysisStage':
    return AnalysisStage(obj)

  def to_dict(self) -> str:
    return self.value

@dataclass
class TransitionLogEntry:
  timestamp: int
  from_stage: AnalysisStage
  to_stage: AnalysisStage
  reason: str
  run_id: Optional[str] = None
  triggered_by: Optional[str] = None

  @staticmethod
  def from_dict(obj: Any) -> 'TransitionLogEntry':
    if not isinstance(obj, dict):
      return obj
    timestamp = obj.get("timestamp")
    from_stage = AnalysisStage.from_dict(obj.get("from_stage"))
    to_stage = AnalysisStage.from_dict(obj.get("to_stage"))
    reason = obj.get("reason")
    run_id = obj.get("run_id")
    triggered_by = (obj.get("triggered_by")) if obj.get("triggered_by") is not None else None
    return TransitionLogEntry(timestamp, from_stage, to_stage, reason, run_id=run_id, triggered_by=triggered_by)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.timestamp is not None:
      result["timestamp"] = self.timestamp
    if self.from_stage is not None:
      result["from_stage"] = self.from_stage.to_dict()
    if self.to_stage is not None:
      result["to_stage"] = self.to_stage.to_dict()
    if self.reason is not None:
      result["reason"] = self.reason
    if self.run_id is not None:
      result["run_id"] = self.run_id
    if self.triggered_by is not None:
      result["triggered_by"] = self.triggered_by
    return result

@dataclass
class AnalysisStatusResponse:
  analysis_id: str
  stage: AnalysisStage
  mcu: Mcu
  fuzzer_config: FuzzerConfig
  image: Image
  run_ids: List[str]
  transition_log: List[TransitionLogEntry]
  created_at: int
  updated_at: int
  queued: Optional[bool] = None
  error: Optional[str] = None
  creator: Optional[CreatorInfo] = None
  tags: Optional[List[str]] = None
  started_at: Optional[int] = None
  timeout_secs: Optional[int] = None

  @staticmethod
  def from_dict(obj: Any) -> 'AnalysisStatusResponse':
    if not isinstance(obj, dict):
      return obj
    analysis_id = obj.get("analysis_id")
    stage = AnalysisStage.from_dict(obj.get("stage"))
    queued = obj.get("queued")
    mcu = Mcu.from_dict(obj.get("mcu"))
    fuzzer_config = FuzzerConfig.from_dict(obj.get("fuzzer_config"))
    image = Image.from_dict(obj.get("image"))
    run_ids = obj.get("run_ids", [])
    transition_log = [TransitionLogEntry.from_dict(it) for it in obj.get("transition_log", [])]
    error = (obj.get("error")) if obj.get("error") is not None else None
    created_at = obj.get("created_at")
    updated_at = obj.get("updated_at")
    creator = CreatorInfo.from_dict(obj.get("creator"))
    tags = obj.get("tags", [])
    started_at = (obj.get("started_at")) if obj.get("started_at") is not None else None
    timeout_secs = obj.get("timeout_secs")
    return AnalysisStatusResponse(analysis_id, stage, mcu, fuzzer_config, image, run_ids, transition_log, created_at, updated_at, queued=queued, error=error, creator=creator, tags=tags, started_at=started_at, timeout_secs=timeout_secs)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.analysis_id is not None:
      result["analysis_id"] = self.analysis_id
    if self.stage is not None:
      result["stage"] = self.stage.to_dict()
    if self.queued is not None:
      result["queued"] = self.queued
    if self.mcu is not None:
      result["mcu"] = self.mcu.to_dict()
    if self.fuzzer_config is not None:
      result["fuzzer_config"] = self.fuzzer_config.to_dict()
    if self.image is not None:
      result["image"] = self.image.to_dict()
    if self.run_ids is not None:
      result["run_ids"] = self.run_ids
    if self.transition_log is not None:
      result["transition_log"] = [it.to_dict() for it in self.transition_log]
    if self.error is not None:
      result["error"] = self.error
    if self.created_at is not None:
      result["created_at"] = self.created_at
    if self.updated_at is not None:
      result["updated_at"] = self.updated_at
    if self.creator is not None:
      result["creator"] = self.creator.to_dict()
    if self.tags is not None:
      result["tags"] = self.tags
    if self.started_at is not None:
      result["started_at"] = self.started_at
    if self.timeout_secs is not None:
      result["timeout_secs"] = self.timeout_secs
    return result

@dataclass
class HavocCommonSchema:
  run_summary: RunSummary
  run_stats: RunStats
  mcu: Mcu
  fuzzer_config: FuzzerConfig
  trace_summary: List[Testcase]
  upload_image_request: UploadImageRequest
  infer_config_request: InferConfigRequest
  create_analysis_request: CreateAnalysisRequest
  run_params: RunParams
  run_config: RunConfig
  image: Image
  file_metadata: FileMetadata
  symbol: List[Any]
  inference_response: InferredConfig
  debug_session_id: DebugSessionId
  analysis_status: AnalysisStatusResponse

  @staticmethod
  def from_dict(obj: Any) -> 'HavocCommonSchema':
    if not isinstance(obj, dict):
      return obj
    run_summary = RunSummary.from_dict(obj.get("run_summary"))
    run_stats = RunStats.from_dict(obj.get("run_stats"))
    mcu = Mcu.from_dict(obj.get("mcu"))
    fuzzer_config = FuzzerConfig.from_dict(obj.get("fuzzer_config"))
    trace_summary = [Testcase.from_dict(it) for it in obj.get("trace_summary", [])]
    upload_image_request = UploadImageRequest.from_dict(obj.get("upload_image_request"))
    infer_config_request = InferConfigRequest.from_dict(obj.get("infer_config_request"))
    create_analysis_request = CreateAnalysisRequest.from_dict(obj.get("create_analysis_request"))
    run_params = RunParams.from_dict(obj.get("run_params"))
    run_config = RunConfig.from_dict(obj.get("run_config"))
    image = Image.from_dict(obj.get("image"))
    file_metadata = FileMetadata.from_dict(obj.get("file_metadata"))
    symbol = obj.get("symbol", [])
    inference_response = InferredConfig.from_dict(obj.get("inference_response"))
    debug_session_id = DebugSessionId.from_dict(obj.get("debug_session_id"))
    analysis_status = AnalysisStatusResponse.from_dict(obj.get("analysis_status"))
    return HavocCommonSchema(run_summary, run_stats, mcu, fuzzer_config, trace_summary, upload_image_request, infer_config_request, create_analysis_request, run_params, run_config, image, file_metadata, symbol, inference_response, debug_session_id, analysis_status)

  def to_dict(self) -> dict:
    result: dict = {}
    if self.run_summary is not None:
      result["run_summary"] = self.run_summary.to_dict()
    if self.run_stats is not None:
      result["run_stats"] = self.run_stats.to_dict()
    if self.mcu is not None:
      result["mcu"] = self.mcu.to_dict()
    if self.fuzzer_config is not None:
      result["fuzzer_config"] = self.fuzzer_config.to_dict()
    if self.trace_summary is not None:
      result["trace_summary"] = [it.to_dict() for it in self.trace_summary]
    if self.upload_image_request is not None:
      result["upload_image_request"] = self.upload_image_request.to_dict()
    if self.infer_config_request is not None:
      result["infer_config_request"] = self.infer_config_request.to_dict()
    if self.create_analysis_request is not None:
      result["create_analysis_request"] = self.create_analysis_request.to_dict()
    if self.run_params is not None:
      result["run_params"] = self.run_params.to_dict()
    if self.run_config is not None:
      result["run_config"] = self.run_config.to_dict()
    if self.image is not None:
      result["image"] = self.image.to_dict()
    if self.file_metadata is not None:
      result["file_metadata"] = self.file_metadata.to_dict()
    if self.symbol is not None:
      result["symbol"] = self.symbol
    if self.inference_response is not None:
      result["inference_response"] = self.inference_response.to_dict()
    if self.debug_session_id is not None:
      result["debug_session_id"] = self.debug_session_id.to_dict()
    if self.analysis_status is not None:
      result["analysis_status"] = self.analysis_status.to_dict()
    return result