package qlog

import (
	
	
	

	
	
	
)

func milliseconds( time.Duration) float64 { return float64(.Nanoseconds()) / 1e6 }

type encoderHelper struct {
	enc *jsontext.Encoder
	err error
}

func ( *encoderHelper) ( jsontext.Token) {
	if .err != nil {
		return
	}
	.err = .enc.WriteToken()
}

type versions []Version

func ( versions) ( *jsontext.Encoder) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginArray)
	for ,  := range  {
		.WriteToken(jsontext.String(fmt.Sprintf("%x", uint32())))
	}
	.WriteToken(jsontext.EndArray)
	return .err
}

type RawInfo struct {
	Length        int // full packet length, including header and AEAD authentication tag
	PayloadLength int // length of the packet payload, excluding AEAD tag
}

func ( RawInfo) ( *jsontext.Encoder) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("length"))
	.WriteToken(jsontext.Uint(uint64(.Length)))
	if .PayloadLength != 0 {
		.WriteToken(jsontext.String("payload_length"))
		.WriteToken(jsontext.Uint(uint64(.PayloadLength)))
	}
	.WriteToken(jsontext.EndObject)
	return .err
}

type PathEndpointInfo struct {
	IPv4 netip.AddrPort
	IPv6 netip.AddrPort
}

func ( PathEndpointInfo) ( *jsontext.Encoder) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	if .IPv4.IsValid() {
		.WriteToken(jsontext.String("ip_v4"))
		.WriteToken(jsontext.String(.IPv4.Addr().String()))
		.WriteToken(jsontext.String("port_v4"))
		.WriteToken(jsontext.Int(int64(.IPv4.Port())))
	}
	if .IPv6.IsValid() {
		.WriteToken(jsontext.String("ip_v6"))
		.WriteToken(jsontext.String(.IPv6.Addr().String()))
		.WriteToken(jsontext.String("port_v6"))
		.WriteToken(jsontext.Int(int64(.IPv6.Port())))
	}
	.WriteToken(jsontext.EndObject)
	return .err
}

type StartedConnection struct {
	Local  PathEndpointInfo
	Remote PathEndpointInfo
}

func ( StartedConnection) () string { return "transport:connection_started" }

func ( StartedConnection) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("local"))
	if  := .Local.encode();  != nil {
		return 
	}
	.WriteToken(jsontext.String("remote"))
	if  := .Remote.encode();  != nil {
		return 
	}
	.WriteToken(jsontext.EndObject)
	return .err
}

type VersionInformation struct {
	ClientVersions, ServerVersions []Version
	ChosenVersion                  Version
}

func ( VersionInformation) () string { return "transport:version_information" }

func ( VersionInformation) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	if len(.ClientVersions) > 0 {
		.WriteToken(jsontext.String("client_versions"))
		if  := versions(.ClientVersions).encode();  != nil {
			return 
		}
	}
	if len(.ServerVersions) > 0 {
		.WriteToken(jsontext.String("server_versions"))
		if  := versions(.ServerVersions).encode();  != nil {
			return 
		}
	}
	.WriteToken(jsontext.String("chosen_version"))
	.WriteToken(jsontext.String(fmt.Sprintf("%x", uint32(.ChosenVersion))))
	.WriteToken(jsontext.EndObject)
	return .err
}

type ConnectionClosed struct {
	Initiator Initiator

	ConnectionError  *TransportErrorCode
	ApplicationError *ApplicationErrorCode

	Reason string

	Trigger ConnectionCloseTrigger
}

func ( ConnectionClosed) () string { return "transport:connection_closed" }

func ( ConnectionClosed) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("initiator"))
	.WriteToken(jsontext.String(string(.Initiator)))
	if .ConnectionError != nil {
		.WriteToken(jsontext.String("connection_error"))
		if .ConnectionError.IsCryptoError() {
			.WriteToken(jsontext.String(fmt.Sprintf("crypto_error_%#x", uint16(*.ConnectionError))))
		} else {
			switch *.ConnectionError {
			case qerr.NoError:
				.WriteToken(jsontext.String("no_error"))
			case qerr.InternalError:
				.WriteToken(jsontext.String("internal_error"))
			case qerr.ConnectionRefused:
				.WriteToken(jsontext.String("connection_refused"))
			case qerr.FlowControlError:
				.WriteToken(jsontext.String("flow_control_error"))
			case qerr.StreamLimitError:
				.WriteToken(jsontext.String("stream_limit_error"))
			case qerr.StreamStateError:
				.WriteToken(jsontext.String("stream_state_error"))
			case qerr.FinalSizeError:
				.WriteToken(jsontext.String("final_size_error"))
			case qerr.FrameEncodingError:
				.WriteToken(jsontext.String("frame_encoding_error"))
			case qerr.TransportParameterError:
				.WriteToken(jsontext.String("transport_parameter_error"))
			case qerr.ConnectionIDLimitError:
				.WriteToken(jsontext.String("connection_id_limit_error"))
			case qerr.ProtocolViolation:
				.WriteToken(jsontext.String("protocol_violation"))
			case qerr.InvalidToken:
				.WriteToken(jsontext.String("invalid_token"))
			case qerr.ApplicationErrorErrorCode:
				.WriteToken(jsontext.String("application_error"))
			case qerr.CryptoBufferExceeded:
				.WriteToken(jsontext.String("crypto_buffer_exceeded"))
			case qerr.KeyUpdateError:
				.WriteToken(jsontext.String("key_update_error"))
			case qerr.AEADLimitReached:
				.WriteToken(jsontext.String("aead_limit_reached"))
			case qerr.NoViablePathError:
				.WriteToken(jsontext.String("no_viable_path"))
			default:
				.WriteToken(jsontext.String("unknown"))
				.WriteToken(jsontext.String("error_code"))
				.WriteToken(jsontext.Uint(uint64(*.ConnectionError)))
			}
		}
	}
	if .ApplicationError != nil {
		.WriteToken(jsontext.String("application_error"))
		.WriteToken(jsontext.String("unknown"))
		.WriteToken(jsontext.String("error_code"))
		.WriteToken(jsontext.Uint(uint64(*.ApplicationError)))
	}
	if .ConnectionError != nil || .ApplicationError != nil {
		.WriteToken(jsontext.String("reason"))
		.WriteToken(jsontext.String(.Reason))
	}
	if .Trigger != "" {
		.WriteToken(jsontext.String("trigger"))
		.WriteToken(jsontext.String(string(.Trigger)))
	}
	.WriteToken(jsontext.EndObject)
	return .err
}

type PacketSent struct {
	Header            PacketHeader
	Raw               RawInfo
	DatagramID        DatagramID
	Frames            []Frame
	ECN               ECN
	IsCoalesced       bool
	Trigger           string
	SupportedVersions []Version
}

func ( PacketSent) () string { return "transport:packet_sent" }

func ( PacketSent) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("header"))
	if  := .Header.encode();  != nil {
		return 
	}
	.WriteToken(jsontext.String("raw"))
	if  := .Raw.encode();  != nil {
		return 
	}
	if .DatagramID != 0 {
		.WriteToken(jsontext.String("datagram_id"))
		.WriteToken(jsontext.Uint(uint64(.DatagramID)))
	}
	if len(.Frames) > 0 {
		.WriteToken(jsontext.String("frames"))
		if  := frames(.Frames).encode();  != nil {
			return 
		}
	}
	if .IsCoalesced {
		.WriteToken(jsontext.String("is_coalesced"))
		.WriteToken(jsontext.True)
	}
	if .ECN != ECNUnsupported {
		.WriteToken(jsontext.String("ecn"))
		.WriteToken(jsontext.String(string(.ECN)))
	}
	if .Trigger != "" {
		.WriteToken(jsontext.String("trigger"))
		.WriteToken(jsontext.String(.Trigger))
	}
	.WriteToken(jsontext.EndObject)
	return .err
}

type PacketReceived struct {
	Header      PacketHeader
	Raw         RawInfo
	DatagramID  DatagramID
	Frames      []Frame
	ECN         ECN
	IsCoalesced bool
	Trigger     string
}

func ( PacketReceived) () string { return "transport:packet_received" }

func ( PacketReceived) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("header"))
	if  := .Header.encode();  != nil {
		return 
	}
	.WriteToken(jsontext.String("raw"))
	if  := .Raw.encode();  != nil {
		return 
	}
	if .DatagramID != 0 {
		.WriteToken(jsontext.String("datagram_id"))
		.WriteToken(jsontext.Uint(uint64(.DatagramID)))
	}
	if len(.Frames) > 0 {
		.WriteToken(jsontext.String("frames"))
		if  := frames(.Frames).encode();  != nil {
			return 
		}
	}
	if .IsCoalesced {
		.WriteToken(jsontext.String("is_coalesced"))
		.WriteToken(jsontext.True)
	}
	if .ECN != ECNUnsupported {
		.WriteToken(jsontext.String("ecn"))
		.WriteToken(jsontext.String(string(.ECN)))
	}
	if .Trigger != "" {
		.WriteToken(jsontext.String("trigger"))
		.WriteToken(jsontext.String(.Trigger))
	}
	.WriteToken(jsontext.EndObject)
	return .err
}

type VersionNegotiationReceived struct {
	Header            PacketHeaderVersionNegotiation
	SupportedVersions []Version
}

func ( VersionNegotiationReceived) () string { return "transport:packet_received" }

func ( VersionNegotiationReceived) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("header"))
	if  := .Header.encode();  != nil {
		return 
	}
	.WriteToken(jsontext.String("supported_versions"))
	if  := versions(.SupportedVersions).encode();  != nil {
		return 
	}
	.WriteToken(jsontext.EndObject)
	return .err
}

type VersionNegotiationSent struct {
	Header            PacketHeaderVersionNegotiation
	SupportedVersions []Version
}

func ( VersionNegotiationSent) () string { return "transport:packet_sent" }

func ( VersionNegotiationSent) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("header"))
	if  := .Header.encode();  != nil {
		return 
	}
	.WriteToken(jsontext.String("supported_versions"))
	if  := versions(.SupportedVersions).encode();  != nil {
		return 
	}
	.WriteToken(jsontext.EndObject)
	return .err
}

type PacketBuffered struct {
	Header     PacketHeader
	Raw        RawInfo
	DatagramID DatagramID
}

func ( PacketBuffered) () string { return "transport:packet_buffered" }

func ( PacketBuffered) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("header"))
	if  := .Header.encode();  != nil {
		return 
	}
	.WriteToken(jsontext.String("raw"))
	if  := .Raw.encode();  != nil {
		return 
	}
	if .DatagramID != 0 {
		.WriteToken(jsontext.String("datagram_id"))
		.WriteToken(jsontext.Uint(uint64(.DatagramID)))
	}
	.WriteToken(jsontext.String("trigger"))
	.WriteToken(jsontext.String("keys_unavailable"))
	.WriteToken(jsontext.EndObject)
	return .err
}

// PacketDropped is the transport:packet_dropped event.
type PacketDropped struct {
	Header     PacketHeader
	Raw        RawInfo
	DatagramID DatagramID
	Trigger    PacketDropReason
}

func ( PacketDropped) () string { return "transport:packet_dropped" }

func ( PacketDropped) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("header"))
	if  := .Header.encode();  != nil {
		return 
	}
	.WriteToken(jsontext.String("raw"))
	if  := .Raw.encode();  != nil {
		return 
	}
	if .DatagramID != 0 {
		.WriteToken(jsontext.String("datagram_id"))
		.WriteToken(jsontext.Uint(uint64(.DatagramID)))
	}
	.WriteToken(jsontext.String("trigger"))
	.WriteToken(jsontext.String(string(.Trigger)))
	.WriteToken(jsontext.EndObject)
	return .err
}

type MTUUpdated struct {
	Value int
	Done  bool
}

func ( MTUUpdated) () string { return "recovery:mtu_updated" }

func ( MTUUpdated) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("mtu"))
	.WriteToken(jsontext.Uint(uint64(.Value)))
	.WriteToken(jsontext.String("done"))
	.WriteToken(jsontext.Bool(.Done))
	.WriteToken(jsontext.EndObject)
	return .err
}

// MetricsUpdated logs RTT and congestion metrics as defined in the
// recovery:metrics_updated event.
// The PTO count is logged via PTOCountUpdated.
type MetricsUpdated struct {
	MinRTT           time.Duration
	SmoothedRTT      time.Duration
	LatestRTT        time.Duration
	RTTVariance      time.Duration
	CongestionWindow int
	BytesInFlight    int
	PacketsInFlight  int
}

func ( MetricsUpdated) () string { return "recovery:metrics_updated" }

func ( MetricsUpdated) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	if .MinRTT != 0 {
		.WriteToken(jsontext.String("min_rtt"))
		.WriteToken(jsontext.Float(milliseconds(.MinRTT)))
	}
	if .SmoothedRTT != 0 {
		.WriteToken(jsontext.String("smoothed_rtt"))
		.WriteToken(jsontext.Float(milliseconds(.SmoothedRTT)))
	}
	if .LatestRTT != 0 {
		.WriteToken(jsontext.String("latest_rtt"))
		.WriteToken(jsontext.Float(milliseconds(.LatestRTT)))
	}
	if .RTTVariance != 0 {
		.WriteToken(jsontext.String("rtt_variance"))
		.WriteToken(jsontext.Float(milliseconds(.RTTVariance)))
	}
	if .CongestionWindow != 0 {
		.WriteToken(jsontext.String("congestion_window"))
		.WriteToken(jsontext.Uint(uint64(.CongestionWindow)))
	}
	if .BytesInFlight != 0 {
		.WriteToken(jsontext.String("bytes_in_flight"))
		.WriteToken(jsontext.Uint(uint64(.BytesInFlight)))
	}
	if .PacketsInFlight != 0 {
		.WriteToken(jsontext.String("packets_in_flight"))
		.WriteToken(jsontext.Uint(uint64(.PacketsInFlight)))
	}
	.WriteToken(jsontext.EndObject)
	return .err
}

// PTOCountUpdated logs the pto_count value of the
// recovery:metrics_updated event.
type PTOCountUpdated struct {
	PTOCount uint32
}

func ( PTOCountUpdated) () string { return "recovery:metrics_updated" }

func ( PTOCountUpdated) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("pto_count"))
	.WriteToken(jsontext.Uint(uint64(.PTOCount)))
	.WriteToken(jsontext.EndObject)
	return .err
}

type PacketLost struct {
	Header  PacketHeader
	Trigger PacketLossReason
}

func ( PacketLost) () string { return "recovery:packet_lost" }

func ( PacketLost) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("header"))
	if  := .Header.encode();  != nil {
		return 
	}
	.WriteToken(jsontext.String("trigger"))
	.WriteToken(jsontext.String(string(.Trigger)))
	.WriteToken(jsontext.EndObject)
	return .err
}

type SpuriousLoss struct {
	EncryptionLevel  protocol.EncryptionLevel
	PacketNumber     protocol.PacketNumber
	PacketReordering uint64
	TimeReordering   time.Duration
}

func ( SpuriousLoss) () string { return "recovery:spurious_loss" }

func ( SpuriousLoss) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("packet_number_space"))
	.WriteToken(jsontext.String(encLevelToPacketNumberSpace(.EncryptionLevel)))
	.WriteToken(jsontext.String("packet_number"))
	.WriteToken(jsontext.Uint(uint64(.PacketNumber)))
	.WriteToken(jsontext.String("reordering_packets"))
	.WriteToken(jsontext.Uint(.PacketReordering))
	.WriteToken(jsontext.String("reordering_time"))
	.WriteToken(jsontext.Float(milliseconds(.TimeReordering)))
	.WriteToken(jsontext.EndObject)
	return .err
}

type KeyUpdated struct {
	Trigger  KeyUpdateTrigger
	KeyType  KeyType
	KeyPhase KeyPhase // only set for 1-RTT keys
	// we don't log the keys here, so we don't need `old` and `new`.
}

func ( KeyUpdated) () string { return "security:key_updated" }

func ( KeyUpdated) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("trigger"))
	.WriteToken(jsontext.String(string(.Trigger)))
	.WriteToken(jsontext.String("key_type"))
	.WriteToken(jsontext.String(string(.KeyType)))
	if .KeyType == KeyTypeClient1RTT || .KeyType == KeyTypeServer1RTT {
		.WriteToken(jsontext.String("key_phase"))
		.WriteToken(jsontext.Uint(uint64(.KeyPhase)))
	}
	.WriteToken(jsontext.EndObject)
	return .err
}

type KeyDiscarded struct {
	KeyType  KeyType
	KeyPhase KeyPhase // only set for 1-RTT keys
}

func ( KeyDiscarded) () string { return "security:key_discarded" }

func ( KeyDiscarded) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	if .KeyType != KeyTypeClient1RTT && .KeyType != KeyTypeServer1RTT {
		.WriteToken(jsontext.String("trigger"))
		.WriteToken(jsontext.String("tls"))
	}
	.WriteToken(jsontext.String("key_type"))
	.WriteToken(jsontext.String(string(.KeyType)))
	if .KeyType == KeyTypeClient1RTT || .KeyType == KeyTypeServer1RTT {
		.WriteToken(jsontext.String("key_phase"))
		.WriteToken(jsontext.Uint(uint64(.KeyPhase)))
	}
	.WriteToken(jsontext.EndObject)
	return .err
}

type ParametersSet struct {
	Restore                         bool
	Initiator                       Initiator
	SentBy                          protocol.Perspective
	OriginalDestinationConnectionID protocol.ConnectionID
	InitialSourceConnectionID       protocol.ConnectionID
	RetrySourceConnectionID         *protocol.ConnectionID
	StatelessResetToken             *protocol.StatelessResetToken
	DisableActiveMigration          bool
	MaxIdleTimeout                  time.Duration
	MaxUDPPayloadSize               protocol.ByteCount
	AckDelayExponent                uint8
	MaxAckDelay                     time.Duration
	ActiveConnectionIDLimit         uint64
	InitialMaxData                  protocol.ByteCount
	InitialMaxStreamDataBidiLocal   protocol.ByteCount
	InitialMaxStreamDataBidiRemote  protocol.ByteCount
	InitialMaxStreamDataUni         protocol.ByteCount
	InitialMaxStreamsBidi           int64
	InitialMaxStreamsUni            int64
	PreferredAddress                *PreferredAddress
	MaxDatagramFrameSize            protocol.ByteCount
	EnableResetStreamAt             bool
}

func ( ParametersSet) () string {
	if .Restore {
		return "transport:parameters_restored"
	}
	return "transport:parameters_set"
}

func ( ParametersSet) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	if !.Restore {
		.WriteToken(jsontext.String("initiator"))
		.WriteToken(jsontext.String(string(.Initiator)))
		if .SentBy == protocol.PerspectiveServer {
			.WriteToken(jsontext.String("original_destination_connection_id"))
			.WriteToken(jsontext.String(.OriginalDestinationConnectionID.String()))
			if .StatelessResetToken != nil {
				.WriteToken(jsontext.String("stateless_reset_token"))
				.WriteToken(jsontext.String(fmt.Sprintf("%x", .StatelessResetToken[:])))
			}
			if .RetrySourceConnectionID != nil {
				.WriteToken(jsontext.String("retry_source_connection_id"))
				.WriteToken(jsontext.String((*.RetrySourceConnectionID).String()))
			}
		}
		.WriteToken(jsontext.String("initial_source_connection_id"))
		.WriteToken(jsontext.String(.InitialSourceConnectionID.String()))
	}
	.WriteToken(jsontext.String("disable_active_migration"))
	.WriteToken(jsontext.Bool(.DisableActiveMigration))
	if .MaxIdleTimeout != 0 {
		.WriteToken(jsontext.String("max_idle_timeout"))
		.WriteToken(jsontext.Float(milliseconds(.MaxIdleTimeout)))
	}
	if .MaxUDPPayloadSize != 0 {
		.WriteToken(jsontext.String("max_udp_payload_size"))
		.WriteToken(jsontext.Int(int64(.MaxUDPPayloadSize)))
	}
	if .AckDelayExponent != 0 {
		.WriteToken(jsontext.String("ack_delay_exponent"))
		.WriteToken(jsontext.Uint(uint64(.AckDelayExponent)))
	}
	if .MaxAckDelay != 0 {
		.WriteToken(jsontext.String("max_ack_delay"))
		.WriteToken(jsontext.Float(milliseconds(.MaxAckDelay)))
	}
	if .ActiveConnectionIDLimit != 0 {
		.WriteToken(jsontext.String("active_connection_id_limit"))
		.WriteToken(jsontext.Uint(.ActiveConnectionIDLimit))
	}
	if .InitialMaxData != 0 {
		.WriteToken(jsontext.String("initial_max_data"))
		.WriteToken(jsontext.Int(int64(.InitialMaxData)))
	}
	if .InitialMaxStreamDataBidiLocal != 0 {
		.WriteToken(jsontext.String("initial_max_stream_data_bidi_local"))
		.WriteToken(jsontext.Int(int64(.InitialMaxStreamDataBidiLocal)))
	}
	if .InitialMaxStreamDataBidiRemote != 0 {
		.WriteToken(jsontext.String("initial_max_stream_data_bidi_remote"))
		.WriteToken(jsontext.Int(int64(.InitialMaxStreamDataBidiRemote)))
	}
	if .InitialMaxStreamDataUni != 0 {
		.WriteToken(jsontext.String("initial_max_stream_data_uni"))
		.WriteToken(jsontext.Int(int64(.InitialMaxStreamDataUni)))
	}
	if .InitialMaxStreamsBidi != 0 {
		.WriteToken(jsontext.String("initial_max_streams_bidi"))
		.WriteToken(jsontext.Int(.InitialMaxStreamsBidi))
	}
	if .InitialMaxStreamsUni != 0 {
		.WriteToken(jsontext.String("initial_max_streams_uni"))
		.WriteToken(jsontext.Int(.InitialMaxStreamsUni))
	}
	if .PreferredAddress != nil {
		.WriteToken(jsontext.String("preferred_address"))
		if  := .PreferredAddress.encode();  != nil {
			return 
		}
	}
	if .MaxDatagramFrameSize != protocol.InvalidByteCount {
		.WriteToken(jsontext.String("max_datagram_frame_size"))
		.WriteToken(jsontext.Int(int64(.MaxDatagramFrameSize)))
	}
	if .EnableResetStreamAt {
		.WriteToken(jsontext.String("reset_stream_at"))
		.WriteToken(jsontext.True)
	}
	.WriteToken(jsontext.EndObject)
	return .err
}

type PreferredAddress struct {
	IPv4, IPv6          netip.AddrPort
	ConnectionID        protocol.ConnectionID
	StatelessResetToken protocol.StatelessResetToken
}

func ( PreferredAddress) ( *jsontext.Encoder) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	if .IPv4.IsValid() {
		.WriteToken(jsontext.String("ip_v4"))
		.WriteToken(jsontext.String(.IPv4.Addr().String()))
		.WriteToken(jsontext.String("port_v4"))
		.WriteToken(jsontext.Uint(uint64(.IPv4.Port())))
	}
	if .IPv6.IsValid() {
		.WriteToken(jsontext.String("ip_v6"))
		.WriteToken(jsontext.String(.IPv6.Addr().String()))
		.WriteToken(jsontext.String("port_v6"))
		.WriteToken(jsontext.Uint(uint64(.IPv6.Port())))
	}
	.WriteToken(jsontext.String("connection_id"))
	.WriteToken(jsontext.String(.ConnectionID.String()))
	.WriteToken(jsontext.String("stateless_reset_token"))
	.WriteToken(jsontext.String(fmt.Sprintf("%x", .StatelessResetToken)))
	.WriteToken(jsontext.EndObject)
	return .err
}

type LossTimerUpdated struct {
	Type      LossTimerUpdateType
	TimerType TimerType
	EncLevel  EncryptionLevel
	Time      time.Time
}

func ( LossTimerUpdated) () string { return "recovery:loss_timer_updated" }

func ( LossTimerUpdated) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("event_type"))
	.WriteToken(jsontext.String(string(.Type)))
	.WriteToken(jsontext.String("timer_type"))
	.WriteToken(jsontext.String(string(.TimerType)))
	.WriteToken(jsontext.String("packet_number_space"))
	.WriteToken(jsontext.String(encLevelToPacketNumberSpace(.EncLevel)))
	if .Type == LossTimerUpdateTypeSet {
		.WriteToken(jsontext.String("delta"))
		.WriteToken(jsontext.Float(milliseconds(.Time.Sub())))
	}
	.WriteToken(jsontext.EndObject)
	return .err
}

type eventLossTimerCanceled struct{}

func ( eventLossTimerCanceled) () string { return "recovery:loss_timer_updated" }

func ( eventLossTimerCanceled) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("event_type"))
	.WriteToken(jsontext.String("cancelled"))
	.WriteToken(jsontext.EndObject)
	return .err
}

type CongestionStateUpdated struct {
	State CongestionState
}

func ( CongestionStateUpdated) () string { return "recovery:congestion_state_updated" }

func ( CongestionStateUpdated) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("new"))
	.WriteToken(jsontext.String(.State.String()))
	.WriteToken(jsontext.EndObject)
	return .err
}

type ECNStateUpdated struct {
	State   ECNState
	Trigger string
}

func ( ECNStateUpdated) () string { return "recovery:ecn_state_updated" }

func ( ECNStateUpdated) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("new"))
	.WriteToken(jsontext.String(string(.State)))
	if .Trigger != "" {
		.WriteToken(jsontext.String("trigger"))
		.WriteToken(jsontext.String(.Trigger))
	}
	.WriteToken(jsontext.EndObject)
	return .err
}

type ALPNInformation struct {
	ChosenALPN string
}

func ( ALPNInformation) () string { return "transport:alpn_information" }

func ( ALPNInformation) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("chosen_alpn"))
	.WriteToken(jsontext.String(.ChosenALPN))
	.WriteToken(jsontext.EndObject)
	return .err
}

// DebugEvent is a generic event that can be used to log arbitrary messages.
type DebugEvent struct {
	EventName string
	Message   string
}

func ( DebugEvent) () string {
	if .EventName == "" {
		return "transport:debug"
	}
	return fmt.Sprintf("transport:%s", .EventName)
}

func ( DebugEvent) ( *jsontext.Encoder,  time.Time) error {
	 := encoderHelper{enc: }
	.WriteToken(jsontext.BeginObject)
	.WriteToken(jsontext.String("message"))
	.WriteToken(jsontext.String(.Message))
	.WriteToken(jsontext.EndObject)
	return .err
}