From 0a885262a157c04ab16796074a7f693062907bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Mon, 17 Apr 2023 12:21:25 +0200 Subject: [PATCH] flatbuffers --- .github/workflows/mediasoup-node.yaml | 13 + .github/workflows/mediasoup-rust.yaml | 14 +- .gitignore | 4 + node/.eslintignore | 1 + node/src/ActiveSpeakerObserver.ts | 12 +- node/src/AudioLevelObserver.ts | 41 +- node/src/Channel.ts | 299 +- node/src/Consumer.ts | 615 +- node/src/DataConsumer.ts | 212 +- node/src/DataProducer.ts | 125 +- node/src/DirectTransport.ts | 155 +- node/src/PayloadChannel.ts | 402 - node/src/PipeTransport.ts | 287 +- node/src/PlainTransport.ts | 272 +- node/src/Producer.ts | 261 +- node/src/Router.ts | 386 +- node/src/RtpObserver.ts | 61 +- node/src/RtpParameters.ts | 447 +- node/src/RtpStream.ts | 138 + node/src/SctpParameters.ts | 63 + node/src/SrtpParameters.ts | 23 + node/src/Transport.ts | 711 +- node/src/WebRtcServer.ts | 22 +- node/src/WebRtcTransport.ts | 354 +- node/src/Worker.ts | 147 +- node/src/ortc.ts | 43 +- node/src/tests/test-Consumer.ts | 189 +- node/src/tests/test-DataConsumer.ts | 44 +- node/src/tests/test-DataProducer.ts | 46 +- node/src/tests/test-DirectTransport.ts | 2 +- node/src/tests/test-PlainTransport.ts | 2 +- node/src/tests/test-Producer.ts | 96 +- node/src/tests/test-Router.ts | 5 +- node/src/tests/test-WebRtcServer.ts | 15 +- node/src/tests/test-WebRtcTransport.ts | 94 +- node/src/tests/test-Worker.ts | 5 +- node/src/tests/test-ortc.ts | 9 +- node/src/utils.ts | 134 + npm-scripts.js | 71 +- package-lock.json | 11 + package.json | 5 + rust/Cargo.toml | 1 + rust/src/data_structures.rs | 3 + rust/src/fbs.rs | 45093 ++++++++++++++++ rust/src/lib.rs | 1 + rust/src/messages.rs | 19 +- rust/src/router.rs | 9 +- rust/src/router/consumer.rs | 43 +- rust/src/router/data_consumer.rs | 67 +- rust/src/router/data_producer.rs | 11 +- rust/src/router/direct_transport.rs | 58 +- rust/src/router/pipe_transport.rs | 9 +- rust/src/router/plain_transport.rs | 9 +- rust/src/router/producer.rs | 13 +- rust/src/router/transport.rs | 8 +- rust/src/router/webrtc_transport.rs | 9 +- rust/src/worker.rs | 92 +- rust/src/worker/channel.rs | 384 +- rust/src/worker/common.rs | 97 +- rust/src/worker/payload_channel.rs | 398 - rust/src/worker/utils.rs | 34 +- rust/src/worker/utils/channel_read_fn.rs | 93 +- rust/src/worker/utils/channel_write_fn.rs | 73 +- rust/tests/integration/router.rs | 3 +- rust/tests/integration/webrtc_server.rs | 3 +- rust/tests/integration/worker.rs | 3 +- worker/.clang-format | 2 +- worker/Makefile | 20 +- worker/deps/libwebrtc/meson.build | 3 +- worker/fbs/activeSpeakerObserver.fbs | 11 + worker/fbs/audioLevelObserver.fbs | 18 + worker/fbs/common.fbs | 28 + worker/fbs/consumer.fbs | 144 + worker/fbs/dataConsumer.fbs | 59 + worker/fbs/dataProducer.fbs | 38 + worker/fbs/directTransport.fbs | 21 + worker/fbs/log.fbs | 6 + worker/fbs/message.fbs | 27 + worker/fbs/notification.fbs | 78 + worker/fbs/pipeTransport.fbs | 33 + worker/fbs/plainTransport.fbs | 54 + worker/fbs/producer.fbs | 79 + worker/fbs/request.fbs | 122 + worker/fbs/response.fbs | 50 + worker/fbs/router.fbs | 59 + worker/fbs/rtpObserver.fbs | 10 + worker/fbs/rtpParameters.fbs | 104 + worker/fbs/rtpStream.fbs | 81 + worker/fbs/rtxStream.fbs | 16 + worker/fbs/sctpAssociation.fbs | 11 + worker/fbs/sctpParameters.fbs | 25 + worker/fbs/transport.fbs | 220 + worker/fbs/webRtcServer.fbs | 34 + worker/fbs/webRtcTransport.fbs | 98 + worker/fbs/worker.fbs | 56 + .../include/Channel/ChannelNotification.hpp | 33 + worker/include/Channel/ChannelNotifier.hpp | 53 +- worker/include/Channel/ChannelRequest.hpp | 115 +- worker/include/Channel/ChannelSocket.hpp | 20 +- worker/include/ChannelMessageRegistrator.hpp | 18 +- .../PayloadChannelNotification.hpp | 44 - .../PayloadChannel/PayloadChannelNotifier.hpp | 39 - .../PayloadChannel/PayloadChannelRequest.hpp | 57 - .../PayloadChannel/PayloadChannelSocket.hpp | 133 - worker/include/RTC/ActiveSpeakerObserver.hpp | 6 +- worker/include/RTC/AudioLevelObserver.hpp | 8 +- worker/include/RTC/Consumer.hpp | 19 +- worker/include/RTC/DataConsumer.hpp | 18 +- worker/include/RTC/DataProducer.hpp | 16 +- worker/include/RTC/DirectTransport.hpp | 15 +- worker/include/RTC/IceCandidate.hpp | 8 +- worker/include/RTC/Parameters.hpp | 9 +- worker/include/RTC/PipeConsumer.hpp | 11 +- worker/include/RTC/PipeTransport.hpp | 16 +- worker/include/RTC/PlainTransport.hpp | 19 +- worker/include/RTC/PortManager.hpp | 2 - worker/include/RTC/Producer.hpp | 23 +- worker/include/RTC/Router.hpp | 19 +- worker/include/RTC/RtpDictionaries.hpp | 40 +- worker/include/RTC/RtpListener.hpp | 6 +- worker/include/RTC/RtpObserver.hpp | 3 - worker/include/RTC/RtpPacket.hpp | 5 - worker/include/RTC/RtpStream.hpp | 12 +- worker/include/RTC/RtpStreamRecv.hpp | 3 +- worker/include/RTC/RtpStreamSend.hpp | 3 +- worker/include/RTC/RtxStream.hpp | 9 +- worker/include/RTC/SctpAssociation.hpp | 6 +- worker/include/RTC/SctpDictionaries.hpp | 10 +- worker/include/RTC/SctpListener.hpp | 6 +- worker/include/RTC/Shared.hpp | 5 +- worker/include/RTC/SimpleConsumer.hpp | 12 +- worker/include/RTC/SimulcastConsumer.hpp | 12 +- worker/include/RTC/SvcConsumer.hpp | 11 +- worker/include/RTC/Transport.hpp | 47 +- worker/include/RTC/TransportTuple.hpp | 7 +- worker/include/RTC/WebRtcServer.hpp | 19 +- worker/include/RTC/WebRtcTransport.hpp | 17 +- worker/include/Utils.hpp | 25 - worker/include/Worker.hpp | 39 +- worker/include/common.hpp | 24 - worker/include/lib.hpp | 6 +- worker/meson.build | 23 +- worker/src/Channel/ChannelNotification.cpp | 41 + worker/src/Channel/ChannelNotifier.cpp | 53 - worker/src/Channel/ChannelRequest.cpp | 250 +- worker/src/Channel/ChannelSocket.cpp | 145 +- worker/src/ChannelMessageRegistrator.cpp | 98 +- .../PayloadChannelNotification.cpp | 80 - .../PayloadChannel/PayloadChannelNotifier.cpp | 43 - .../PayloadChannel/PayloadChannelRequest.cpp | 165 - .../PayloadChannel/PayloadChannelSocket.cpp | 538 - worker/src/RTC/ActiveSpeakerObserver.cpp | 33 +- worker/src/RTC/AudioLevelObserver.cpp | 72 +- worker/src/RTC/Consumer.cpp | 290 +- worker/src/RTC/DataConsumer.cpp | 207 +- worker/src/RTC/DataProducer.cpp | 145 +- worker/src/RTC/DirectTransport.cpp | 132 +- worker/src/RTC/IceCandidate.cpp | 45 +- worker/src/RTC/PipeConsumer.cpp | 64 +- worker/src/RTC/PipeTransport.cpp | 239 +- worker/src/RTC/PlainTransport.cpp | 386 +- worker/src/RTC/PortManager.cpp | 51 - worker/src/RTC/Producer.cpp | 494 +- worker/src/RTC/Router.cpp | 346 +- worker/src/RTC/RtpDictionaries/Parameters.cpp | 133 +- .../src/RTC/RtpDictionaries/RtcpFeedback.cpp | 29 +- .../RTC/RtpDictionaries/RtcpParameters.cpp | 44 +- .../RtpDictionaries/RtpCodecParameters.cpp | 108 +- .../RtpDictionaries/RtpEncodingParameters.cpp | 119 +- .../RtpHeaderExtensionParameters.cpp | 50 +- .../src/RTC/RtpDictionaries/RtpParameters.cpp | 98 +- .../RTC/RtpDictionaries/RtpRtxParameters.cpp | 28 +- worker/src/RTC/RtpListener.cpp | 28 +- worker/src/RTC/RtpObserver.cpp | 34 +- worker/src/RTC/RtpPacket.cpp | 59 - worker/src/RTC/RtpStream.cpp | 112 +- worker/src/RTC/RtpStreamRecv.cpp | 35 +- worker/src/RTC/RtpStreamSend.cpp | 16 +- worker/src/RTC/RtxStream.cpp | 27 +- worker/src/RTC/SctpAssociation.cpp | 39 +- .../SctpDictionaries/SctpStreamParameters.cpp | 62 +- worker/src/RTC/SctpListener.cpp | 14 +- worker/src/RTC/Shared.cpp | 8 +- worker/src/RTC/SimpleConsumer.cpp | 82 +- worker/src/RTC/SimulcastConsumer.cpp | 182 +- worker/src/RTC/SvcConsumer.cpp | 185 +- worker/src/RTC/Transport.cpp | 987 +- worker/src/RTC/TransportTuple.cpp | 34 +- worker/src/RTC/WebRtcServer.cpp | 207 +- worker/src/RTC/WebRtcTransport.cpp | 540 +- worker/src/Settings.cpp | 25 +- worker/src/Utils/String.cpp | 39 - worker/src/Worker.cpp | 318 +- worker/src/lib.cpp | 40 +- worker/src/lib.rs | 41 - worker/src/main.cpp | 4 - worker/subprojects/flatbuffers.wrap | 14 + worker/subprojects/nlohmann_json.wrap | 10 - worker/test/src/RTC/TestRtpPacketH264Svc.cpp | 1 + worker/test/src/Utils/TestJson.cpp | 105 - worker/test/src/Utils/TestString.cpp | 37 - 201 files changed, 54720 insertions(+), 8018 deletions(-) create mode 100644 node/.eslintignore delete mode 100644 node/src/PayloadChannel.ts create mode 100644 node/src/RtpStream.ts create mode 100644 rust/src/fbs.rs delete mode 100644 rust/src/worker/payload_channel.rs create mode 100644 worker/fbs/activeSpeakerObserver.fbs create mode 100644 worker/fbs/audioLevelObserver.fbs create mode 100644 worker/fbs/common.fbs create mode 100644 worker/fbs/consumer.fbs create mode 100644 worker/fbs/dataConsumer.fbs create mode 100644 worker/fbs/dataProducer.fbs create mode 100644 worker/fbs/directTransport.fbs create mode 100644 worker/fbs/log.fbs create mode 100644 worker/fbs/message.fbs create mode 100644 worker/fbs/notification.fbs create mode 100644 worker/fbs/pipeTransport.fbs create mode 100644 worker/fbs/plainTransport.fbs create mode 100644 worker/fbs/producer.fbs create mode 100644 worker/fbs/request.fbs create mode 100644 worker/fbs/response.fbs create mode 100644 worker/fbs/router.fbs create mode 100644 worker/fbs/rtpObserver.fbs create mode 100644 worker/fbs/rtpParameters.fbs create mode 100644 worker/fbs/rtpStream.fbs create mode 100644 worker/fbs/rtxStream.fbs create mode 100644 worker/fbs/sctpAssociation.fbs create mode 100644 worker/fbs/sctpParameters.fbs create mode 100644 worker/fbs/transport.fbs create mode 100644 worker/fbs/webRtcServer.fbs create mode 100644 worker/fbs/webRtcTransport.fbs create mode 100644 worker/fbs/worker.fbs create mode 100644 worker/include/Channel/ChannelNotification.hpp delete mode 100644 worker/include/PayloadChannel/PayloadChannelNotification.hpp delete mode 100644 worker/include/PayloadChannel/PayloadChannelNotifier.hpp delete mode 100644 worker/include/PayloadChannel/PayloadChannelRequest.hpp delete mode 100644 worker/include/PayloadChannel/PayloadChannelSocket.hpp create mode 100644 worker/src/Channel/ChannelNotification.cpp delete mode 100644 worker/src/PayloadChannel/PayloadChannelNotification.cpp delete mode 100644 worker/src/PayloadChannel/PayloadChannelNotifier.cpp delete mode 100644 worker/src/PayloadChannel/PayloadChannelRequest.cpp delete mode 100644 worker/src/PayloadChannel/PayloadChannelSocket.cpp create mode 100644 worker/subprojects/flatbuffers.wrap delete mode 100644 worker/subprojects/nlohmann_json.wrap delete mode 100644 worker/test/src/Utils/TestJson.cpp diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index a925d6dc69..94df8ee384 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -16,14 +16,27 @@ jobs: ci: - os: ubuntu-22.04 node: 16 + cc: gcc + cxx: g++ - os: ubuntu-22.04 node: 18 + cc: gcc + cxx: g++ - os: macos-12 node: 18 + cc: clang + cxx: clang++ - os: windows-2022 node: 18 + cc: cl + cxx: cl + runs-on: ${{ matrix.ci.os }} + env: + CC: ${{ matrix.ci.cc }} + CXX: ${{ matrix.ci.cxx }} + steps: - name: Checkout uses: actions/checkout@v3 diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index e3304d29a7..5dadcf2d6c 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -47,10 +47,10 @@ jobs: command: clippy args: --all-targets -- -D warnings - - name: cargo test - uses: actions-rs/cargo@v1 - env: - KEEP_BUILD_ARTIFACTS: '1' - with: - command: test - args: --verbose + #- name: cargo test + # uses: actions-rs/cargo@v1 + # env: + # KEEP_BUILD_ARTIFACTS: '1' + # with: + # command: test + # args: --verbose diff --git a/.gitignore b/.gitignore index 7f8ebf4acb..c2e4824225 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ ## Node. /node_modules /node/lib +# Flatc generated files. +/node/src/fbs ## Rust. /Cargo.lock @@ -16,6 +18,8 @@ ## Worker. /worker/out /worker/scripts/node_modules +# Flatc generated files. +/worker/include/FBS # Vistual Studio generated Stuff. /worker/**/Debug /worker/**/Release diff --git a/node/.eslintignore b/node/.eslintignore new file mode 100644 index 0000000000..7eadde52eb --- /dev/null +++ b/node/.eslintignore @@ -0,0 +1 @@ +/node/src/fbs diff --git a/node/src/ActiveSpeakerObserver.ts b/node/src/ActiveSpeakerObserver.ts index a9af22c569..9f114c6af5 100644 --- a/node/src/ActiveSpeakerObserver.ts +++ b/node/src/ActiveSpeakerObserver.ts @@ -8,6 +8,8 @@ import { } from './RtpObserver'; import { Producer } from './Producer'; import { AppData } from './types'; +import { Event, Notification } from './fbs/notification'; +import * as FbsActiveSpeakerObserver from './fbs/active-speaker-observer'; export type ActiveSpeakerObserverOptions = { @@ -65,13 +67,17 @@ export class ActiveSpeakerObserver + this.channel.on(this.internal.rtpObserverId, (event: Event, data?: Notification) => { switch (event) { - case 'dominantspeaker': + case Event.ACTIVESPEAKEROBSERVER_DOMINANT_SPEAKER: { - const producer = this.getProducerById(data.producerId); + const notification = new FbsActiveSpeakerObserver.DominantSpeakerNotification(); + + data!.body(notification); + + const producer = this.getProducerById(notification.producerId()!); if (!producer) { diff --git a/node/src/AudioLevelObserver.ts b/node/src/AudioLevelObserver.ts index 597e3ed882..50d315be7f 100644 --- a/node/src/AudioLevelObserver.ts +++ b/node/src/AudioLevelObserver.ts @@ -8,6 +8,9 @@ import { } from './RtpObserver'; import { Producer } from './Producer'; import { AppData } from './types'; +import * as utils from './utils'; +import { Event, Notification } from './fbs/notification'; +import * as FbsAudioLevelObserver from './fbs/audio-level-observer'; export type AudioLevelObserverOptions = { @@ -87,22 +90,27 @@ export class AudioLevelObserver + this.channel.on(this.internal.rtpObserverId, (event: Event, data?: Notification) => { switch (event) { - case 'volumes': + case Event.AUDIOLEVELOBSERVER_VOLUMES: { + const notification = new FbsAudioLevelObserver.VolumesNotification(); + + data!.body(notification); + // Get the corresponding Producer instance and remove entries with // no Producer (it may have been closed in the meanwhile). - const volumes: AudioLevelObserverVolume[] = data - .map(({ producerId, volume }: { producerId: string; volume: number }) => ( - { - producer : this.getProducerById(producerId), - volume - } - )) - .filter(({ producer }: { producer: Producer }) => producer); + const volumes: AudioLevelObserverVolume[] = + utils.parseVector(notification, 'volumes', parseVolume) + .map(({ producerId, volume }: { producerId: string; volume: number }) => ( + { + producer : this.getProducerById(producerId)!, + volume + } + )) + .filter(({ producer }: { producer: Producer }) => producer); if (volumes.length > 0) { @@ -115,7 +123,7 @@ export class AudioLevelObserver + notify( + event: Event, + bodyType?: NotificationBody, + bodyOffset?: number, + handlerId?: string + ): void { - this.#nextId < 4294967295 ? ++this.#nextId : (this.#nextId = 1); + logger.debug('notify() [event:%s]', Event[event]); - const id = this.#nextId; + if (this.#closed) + { + throw new InvalidStateError('Channel closed'); + } - logger.debug('request() [method:%s, id:%s]', method, id); + const handlerIdOffset = this.#bufferBuilder.createString(handlerId); + + let notificationOffset: number; + + if (bodyType && bodyOffset) + { + notificationOffset = Notification.createNotification( + this.#bufferBuilder, handlerIdOffset, event, bodyType, bodyOffset); + } + else + { + notificationOffset = Notification.createNotification( + this.#bufferBuilder, handlerIdOffset, event, NotificationBody.NONE, 0); + } + + const messageOffset = Message.createMessage( + this.#bufferBuilder, + MessageType.NOTIFICATION, + MessageBody.FBS_Notification_Notification, + notificationOffset + ); + + // Finalizes the buffer and adds a 4 byte prefix with the size of the buffer. + this.#bufferBuilder.finishSizePrefixed(messageOffset); + + // Create a new buffer with this data so multiple contiguous flatbuffers + // do not point to the builder buffer overriding others info. + const buffer = new Uint8Array(this.#bufferBuilder.asUint8Array()); + + // Clear the buffer builder so it's reused for the next request. + this.#bufferBuilder.clear(); + + if (buffer.byteLength > MESSAGE_MAX_LEN) + { + throw new Error('Channel request too big'); + } + + try + { + // This may throw if closed or remote side ended. + this.#producerSocket.write(buffer, 'binary'); + } + catch (error) + { + logger.warn('notify() | sending notification failed: %s', String(error)); + + return; + } + } + async request( + method: Method, + bodyType?: RequestBody, + bodyOffset?: number, + handlerId?: string): Promise + { if (this.#closed) { throw new InvalidStateError('Channel closed'); } - const request = `${id}:${method}:${handlerId}:${JSON.stringify(data)}`; + this.#nextId < 4294967295 ? ++this.#nextId : (this.#nextId = 1); + + const id = this.#nextId; + + const handlerIdOffset = this.#bufferBuilder.createString(handlerId); + + let requestOffset: number; - if (Buffer.byteLength(request) > MESSAGE_MAX_LEN) + if (bodyType && bodyOffset) + { + requestOffset = Request.createRequest( + this.#bufferBuilder, id, method, handlerIdOffset, bodyType, bodyOffset); + } + else + { + requestOffset = Request.createRequest( + this.#bufferBuilder, id, method, handlerIdOffset, RequestBody.NONE, 0); + } + + const messageOffset = Message.createMessage( + this.#bufferBuilder, + MessageType.REQUEST, + MessageBody.FBS_Request_Request, + requestOffset + ); + + // Finalizes the buffer and adds a 4 byte prefix with the size of the buffer. + this.#bufferBuilder.finishSizePrefixed(messageOffset); + + // Create a new buffer with this data so multiple contiguous flatbuffers + // do not point to the builder buffer overriding others info. + const buffer = new Uint8Array(this.#bufferBuilder.asUint8Array()); + + // Clear the buffer builder so it's reused for the next request. + this.#bufferBuilder.clear(); + + if (buffer.byteLength > MESSAGE_MAX_LEN) { throw new Error('Channel request too big'); } // This may throw if closed or remote side ended. - this.#producerSocket.write( - Buffer.from(Uint32Array.of(Buffer.byteLength(request)).buffer)); - this.#producerSocket.write(request); + this.#producerSocket.write(buffer, 'binary'); return new Promise((pResolve, pReject) => { const sent: Sent = { id : id, - method : method, + method : Method[method], resolve : (data2) => { if (!this.#sents.delete(id)) @@ -285,67 +405,90 @@ export class Channel extends EnhancedEventEmitter }); } - private processMessage(msg: any): void + private processResponse(response: Response): void { - // If a response, retrieve its associated request. - if (msg.id) + const sent = this.#sents.get(response.id()); + + if (!sent) { - const sent = this.#sents.get(msg.id); + logger.error( + 'received response does not match any sent request [id:%s]', response.id); - if (!sent) - { - logger.error( - 'received response does not match any sent request [id:%s]', msg.id); + return; + } - return; - } + if (response.accepted()) + { + logger.debug( + 'request succeeded [method:%s, id:%s]', sent.method, sent.id); - if (msg.accepted) - { - logger.debug( - 'request succeeded [method:%s, id:%s]', sent.method, sent.id); + sent.resolve(response); + } + else if (response.error()) + { + logger.warn( + 'request failed [method:%s, id:%s]: %s', + sent.method, sent.id, response.reason()); - sent.resolve(msg.data); - } - else if (msg.error) + switch (response.error()!) { - logger.warn( - 'request failed [method:%s, id:%s]: %s', - sent.method, sent.id, msg.reason); - - switch (msg.error) - { - case 'TypeError': - sent.reject(new TypeError(msg.reason)); - break; + case 'TypeError': + sent.reject(new TypeError(response.reason()!)); + break; - default: - sent.reject(new Error(msg.reason)); - } - } - else - { - logger.error( - 'received response is not accepted nor rejected [method:%s, id:%s]', - sent.method, sent.id); + default: + sent.reject(new Error(response.reason()!)); } } - // If a notification emit it to the corresponding entity. - else if (msg.targetId && msg.event) - { - // Due to how Promises work, it may happen that we receive a response - // from the worker followed by a notification from the worker. If we - // emit the notification immediately it may reach its target **before** - // the response, destroying the ordered delivery. So we must wait a bit - // here. - // See https://github.com/versatica/mediasoup/issues/510 - setImmediate(() => this.emit(String(msg.targetId), msg.event, msg.data)); - } - // Otherwise unexpected message. else { logger.error( - 'received message is not a response nor a notification'); + 'received response is not accepted nor rejected [method:%s, id:%s]', + sent.method, sent.id); + } + } + + private processNotification(notification: Notification): void + { + // Due to how Promises work, it may happen that we receive a response + // from the worker followed by a notification from the worker. If we + // emit the notification immediately it may reach its target **before** + // the response, destroying the ordered delivery. So we must wait a bit + // here. + // See https://github.com/versatica/mediasoup/issues/510 + setImmediate(() => this.emit( + notification.handlerId()!, + notification.event(), + notification) + ); + } + + private processLog(pid: number, log: Log): void + { + const logData = log.data()!; + + switch (logData[0]) + { + // 'D' (a debug log). + case 'D': + logger.debug(`[pid:${pid}] ${logData.slice(1)}`); + break; + + // 'W' (a warn log). + case 'W': + logger.warn(`[pid:${pid}] ${logData.slice(1)}`); + break; + + // 'E' (a error log). + case 'E': + logger.error(`[pid:${pid}] ${logData.slice(1)}`); + break; + + // 'X' (a dump log). + case 'X': + // eslint-disable-next-line no-console + console.log(logData.slice(1)); + break; } } } diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index bcf09e3c20..dcad582189 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -1,15 +1,28 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { Channel } from './Channel'; -import { PayloadChannel } from './PayloadChannel'; import { TransportInternal } from './Transport'; import { ProducerStat } from './Producer'; import { MediaKind, RtpCapabilities, - RtpParameters + RtpEncodingParameters, + RtpParameters, + parseRtpEncodingParameters, + parseRtpParameters } from './RtpParameters'; +import { parseRtpStreamStats, RtpStreamSendStats } from './RtpStream'; import { AppData } from './types'; +import * as utils from './utils'; +import { Event, Notification } from './fbs/notification'; +import * as FbsRequest from './fbs/request'; +import * as FbsTransport from './fbs/transport'; +import * as FbsConsumer from './fbs/consumer'; +import * as FbsConsumerTraceInfo from './fbs/consumer/trace-info'; +import * as FbsRtpStream from './fbs/rtp-stream'; +import * as FbsRtxStream from './fbs/rtx-stream'; +import { Type as FbsRtpParametersType } from './fbs/rtp-parameters'; +import * as FbsRtpParameters from './fbs/rtp-parameters'; export type ConsumerOptions = { @@ -65,7 +78,7 @@ export type ConsumerOptions = * Whether this Consumer should ignore DTX packets (only valid for Opus codec). * If set, DTX packets are not forwarded to the remote Consumer. */ - ignoreDtx?: Boolean; + ignoreDtx?: boolean; /** * Whether this Consumer should consume all RTP streams generated by the @@ -142,30 +155,7 @@ export type ConsumerLayers = temporalLayer?: number; }; -export type ConsumerStat = -{ - // Common to all RtpStreams. - type: string; - timestamp: number; - ssrc: number; - rtxSsrc?: number; - kind: string; - mimeType: string; - packetsLost: number; - fractionLost: number; - packetsDiscarded: number; - packetsRetransmitted: number; - packetsRepaired: number; - nackCount: number; - nackPacketCount: number; - pliCount: number; - firCount: number; - score: number; - packetCount: number; - byteCount: number; - bitrate: number; - roundTripTime?: number; -}; +export type ConsumerStat = RtpStreamSendStats; /** * Consumer type. @@ -197,6 +187,35 @@ export type ConsumerObserverEvents = trace: [ConsumerTraceEventData]; }; +export type SimpleConsumerDump = BaseConsumerDump & { + type: string; + rtpStream: RtpStreamDump; +}; + +export type SimulcastConsumerDump = BaseConsumerDump & { + type: string; + rtpStream: RtpStreamDump; + preferredSpatialLayer: number; + targetSpatialLayer: number; + currentSpatialLayer: number; + preferredTemporalLayer: number; + targetTemporalLayer: number; + currentTemporalLayer: number; +}; + +export type SvcConsumerDump = SimulcastConsumerDump; + +export type PipeConsumerDump = BaseConsumerDump & { + type: string; + rtpStreams: RtpStreamDump[]; +}; + +export type ConsumerDump = + SimpleConsumerDump | + SimulcastConsumerDump | + SvcConsumerDump | + PipeConsumerDump; + type ConsumerInternal = TransportInternal & { consumerId: string; @@ -210,6 +229,57 @@ type ConsumerData = type: ConsumerType; }; +type BaseConsumerDump = { + id: string; + producerId:string; + kind:MediaKind; + rtpParameters:RtpParameters; + consumableRtpEncodings?:RtpEncodingParameters[]; + supportedCodecPayloadTypes:number[]; + traceEventTypes:string[]; + paused:boolean; + producerPaused:boolean; + priority:number; +}; + +type RtpStreamParameters = { + encodingIdx: number; + ssrc: number; + payloadType: number; + mimeType: string; + clockRate: number; + rid?: string; + cname: string; + rtxSsrc?: number; + rtxPayloadType?: number; + useNack: boolean; + usePli: boolean; + useFir: boolean; + useInBandFec: boolean; + useDtx: boolean; + spatialLayers: number; + temporalLayers: number; +}; + +type RtpStreamDump = { + params: RtpStreamParameters; + score: number; + rtxStream?: RtxStreamDump; +}; + +type RtxStreamParameters = { + ssrc:number; + payloadType:number; + mimeType:string; + clockRate: number; + rrid?:string; + cname:string; +}; + +type RtxStreamDump = { + params: RtxStreamParameters; +}; + const logger = new Logger('Consumer'); export class Consumer @@ -224,9 +294,6 @@ export class Consumer // Channel instance. readonly #channel: Channel; - // PayloadChannel instance. - #payloadChannel: PayloadChannel; - // Closed flag. #closed = false; @@ -262,7 +329,6 @@ export class Consumer internal, data, channel, - payloadChannel, appData, paused, producerPaused, @@ -273,7 +339,6 @@ export class Consumer internal: ConsumerInternal; data: ConsumerData; channel: Channel; - payloadChannel: PayloadChannel; appData?: ConsumerAppData; paused: boolean; producerPaused: boolean; @@ -288,7 +353,6 @@ export class Consumer this.#internal = internal; this.#data = data; this.#channel = channel; - this.#payloadChannel = payloadChannel; this.#appData = appData || {} as ConsumerAppData; this.#paused = paused; this.#producerPaused = producerPaused; @@ -443,12 +507,18 @@ export class Consumer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.consumerId); - this.#payloadChannel.removeAllListeners(this.#internal.consumerId); - const reqData = { consumerId: this.#internal.consumerId }; + /* Build Request. */ + const requestOffset = new FbsTransport.CloseConsumerRequestT( + this.#internal.consumerId + ).pack(this.#channel.bufferBuilder); - this.#channel.request('transport.closeConsumer', this.#internal.transportId, reqData) - .catch(() => {}); + this.#channel.request( + FbsRequest.Method.TRANSPORT_CLOSE_CONSUMER, + FbsRequest.Body.FBS_Transport_CloseConsumerRequest, + requestOffset, + this.#internal.transportId + ).catch(() => {}); this.emit('@close'); @@ -474,7 +544,6 @@ export class Consumer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.consumerId); - this.#payloadChannel.removeAllListeners(this.#internal.consumerId); this.safeEmit('transportclose'); @@ -485,11 +554,23 @@ export class Consumer /** * Dump Consumer. */ - async dump(): Promise + async dump(): Promise { logger.debug('dump()'); - return this.#channel.request('consumer.dump', this.#internal.consumerId); + const response = await this.#channel.request( + FbsRequest.Method.CONSUMER_DUMP, + undefined, + undefined, + this.#internal.consumerId + ); + + /* Decode Response. */ + const data = new FbsConsumer.DumpResponse(); + + response.body(data); + + return parseConsumerDumpResponse(data); } /** @@ -499,7 +580,19 @@ export class Consumer { logger.debug('getStats()'); - return this.#channel.request('consumer.getStats', this.#internal.consumerId); + const response = await this.#channel.request( + FbsRequest.Method.CONSUMER_GET_STATS, + undefined, + undefined, + this.#internal.consumerId + ); + + /* Decode Response. */ + const data = new FbsConsumer.GetStatsResponse(); + + response.body(data); + + return parseConsumerStats(data); } /** @@ -511,7 +604,12 @@ export class Consumer const wasPaused = this.#paused || this.#producerPaused; - await this.#channel.request('consumer.pause', this.#internal.consumerId); + await this.#channel.request( + FbsRequest.Method.CONSUMER_PAUSE, + undefined, + undefined, + this.#internal.consumerId + ); this.#paused = true; @@ -531,7 +629,12 @@ export class Consumer const wasPaused = this.#paused || this.#producerPaused; - await this.#channel.request('consumer.resume', this.#internal.consumerId); + await this.#channel.request( + FbsRequest.Method.CONSUMER_RESUME, + undefined, + undefined, + this.#internal.consumerId + ); this.#paused = false; @@ -554,12 +657,54 @@ export class Consumer { logger.debug('setPreferredLayers()'); - const reqData = { spatialLayer, temporalLayer }; + if (typeof spatialLayer !== 'number') + { + throw new TypeError('spatialLayer must be a number'); + } + if (temporalLayer && typeof temporalLayer !== 'number') + { + throw new TypeError('if given, temporalLayer must be a number'); + } + + const builder = this.#channel.bufferBuilder; + + const preferredLayersOffset = FbsConsumer.ConsumerLayers.createConsumerLayers( + builder, + spatialLayer, + temporalLayer !== undefined ? temporalLayer : null); + const requestOffset = + FbsConsumer.SetPreferredLayersRequest.createSetPreferredLayersRequest( + builder, preferredLayersOffset); + + const response = await this.#channel.request( + FbsRequest.Method.CONSUMER_SET_PREFERRED_LAYERS, + FbsRequest.Body.FBS_Consumer_SetPreferredLayersRequest, + requestOffset, + this.#internal.consumerId + ); + + /* Decode Response. */ + const data = new FbsConsumer.SetPreferredLayersResponse(); - const data = await this.#channel.request( - 'consumer.setPreferredLayers', this.#internal.consumerId, reqData); + let preferredLayers: ConsumerLayers | undefined; + + // Response is empty for non Simulcast Consumers. + if (response.body(data)) + { + const status = data.unpack(); + + if (status.preferredLayers) + { + preferredLayers = { + spatialLayer : status.preferredLayers.spatialLayer, + temporalLayer : status.preferredLayers.temporalLayer !== null ? + status.preferredLayers.temporalLayer : + undefined + }; + } + } - this.#preferredLayers = data || undefined; + this.#preferredLayers = preferredLayers; } /** @@ -569,12 +714,29 @@ export class Consumer { logger.debug('setPriority()'); - const reqData = { priority }; + if (typeof priority !== 'number' || priority < 0) + { + throw new TypeError('priority must be a positive number'); + } + + const requestOffset = + FbsConsumer.SetPriorityRequest.createSetPriorityRequest( + this.#channel.bufferBuilder, priority); + + const response = await this.#channel.request( + FbsRequest.Method.CONSUMER_SET_PRIORITY, + FbsRequest.Body.FBS_Consumer_SetPriorityRequest, + requestOffset, + this.#internal.consumerId + ); + + const data = new FbsConsumer.SetPriorityResponse(); - const data = await this.#channel.request( - 'consumer.setPriority', this.#internal.consumerId, reqData); + response.body(data); - this.#priority = data.priority; + const status = data.unpack(); + + this.#priority = status.priority; } /** @@ -584,12 +746,7 @@ export class Consumer { logger.debug('unsetPriority()'); - const reqData = { priority: 1 }; - - const data = await this.#channel.request( - 'consumer.setPriority', this.#internal.consumerId, reqData); - - this.#priority = data.priority; + await this.setPriority(1); } /** @@ -599,7 +756,12 @@ export class Consumer { logger.debug('requestKeyFrame()'); - await this.#channel.request('consumer.requestKeyFrame', this.#internal.consumerId); + await this.#channel.request( + FbsRequest.Method.CONSUMER_REQUEST_KEY_FRAME, + undefined, + undefined, + this.#internal.consumerId + ); } /** @@ -609,19 +771,35 @@ export class Consumer { logger.debug('enableTraceEvent()'); - const reqData = { types }; + if (!Array.isArray(types)) + { + throw new TypeError('types must be an array'); + } + if (types.find((type) => typeof type !== 'string')) + { + throw new TypeError('every type must be a string'); + } + + /* Build Request. */ + const requestOffset = new FbsConsumer.EnableTraceEventRequestT( + types + ).pack(this.#channel.bufferBuilder); await this.#channel.request( - 'consumer.enableTraceEvent', this.#internal.consumerId, reqData); + FbsRequest.Method.CONSUMER_ENABLE_TRACE_EVENT, + FbsRequest.Body.FBS_Consumer_EnableTraceEventRequest, + requestOffset, + this.#internal.consumerId + ); } private handleWorkerNotifications(): void { - this.#channel.on(this.#internal.consumerId, (event: string, data?: any) => + this.#channel.on(this.#internal.consumerId, (event: Event, data?: Notification) => { switch (event) { - case 'producerclose': + case Event.CONSUMER_PRODUCER_CLOSE: { if (this.#closed) { @@ -632,7 +810,6 @@ export class Consumer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.consumerId); - this.#payloadChannel.removeAllListeners(this.#internal.consumerId); this.emit('@producerclose'); this.safeEmit('producerclose'); @@ -643,7 +820,7 @@ export class Consumer break; } - case 'producerpause': + case Event.CONSUMER_PRODUCER_PAUSE: { if (this.#producerPaused) { @@ -665,7 +842,7 @@ export class Consumer break; } - case 'producerresume': + case Event.CONSUMER_PRODUCER_RESUME: { if (!this.#producerPaused) { @@ -687,9 +864,13 @@ export class Consumer break; } - case 'score': + case Event.CONSUMER_SCORE: { - const score = data as ConsumerScore; + const notification = new FbsConsumer.ScoreNotification(); + + data!.body(notification); + + const score: ConsumerScore = notification!.score()!.unpack(); this.#score = score; @@ -701,9 +882,15 @@ export class Consumer break; } - case 'layerschange': + case Event.CONSUMER_LAYERS_CHANGE: { - const layers = data as ConsumerLayers | undefined; + const notification = new FbsConsumer.LayersChangeNotification()!; + + data!.body(notification); + + const layers: ConsumerLayers | undefined = notification.layers() ? + parseConsumerLayers(notification.layers()!) : + undefined; this.#currentLayers = layers; @@ -715,9 +902,18 @@ export class Consumer break; } - case 'trace': + case Event.CONSUMER_TRACE: { - const trace = data as ConsumerTraceEventData; + const notification = new FbsConsumer.TraceNotification(); + + data!.body(notification); + + const trace: ConsumerTraceEventData = parseTraceEventData(notification); + + this.safeEmit('trace', trace); + + // Emit observer event. + this.observer.safeEmit('trace', trace); this.safeEmit('trace', trace); @@ -727,38 +923,271 @@ export class Consumer break; } + case Event.CONSUMER_RTP: + { + if (this.#closed) + { + break; + } + + const notification = new FbsConsumer.RtpNotification(); + + data!.body(notification); + + this.safeEmit('rtp', Buffer.from(notification.dataArray()!)); + + break; + } + default: { logger.error('ignoring unknown event "%s"', event); } } }); + } +} - this.#payloadChannel.on( - this.#internal.consumerId, - (event: string, data: any | undefined, payload: Buffer) => - { - switch (event) - { - case 'rtp': - { - if (this.#closed) - { - break; - } +export function parseTraceEventData( + trace: FbsConsumer.TraceNotification +): ConsumerTraceEventData +{ + let info: any; - const packet = payload; + if (trace.infoType() !== FbsConsumer.TraceInfo.NONE) + { + const accessor = trace.info.bind(trace); - this.safeEmit('rtp', packet); + info = FbsConsumerTraceInfo.unionToTraceInfo(trace.infoType(), accessor); - break; - } + trace.info(info); + } - default: - { - logger.error('ignoring unknown event "%s"', event); - } - } - }); + return { + type : fbstraceType2String(trace.type()), + timestamp : Number(trace.timestamp()), + direction : trace.direction() === FbsConsumer.TraceDirection.DIRECTION_IN ? 'in' : 'out', + info : info ? info.unpack() : undefined + }; +} + +function fbstraceType2String(traceType: FbsConsumer.TraceType): ConsumerTraceEventType +{ + switch (traceType) + { + case FbsConsumer.TraceType.KEYFRAME: + return 'keyframe'; + case FbsConsumer.TraceType.FIR: + return 'fir'; + case FbsConsumer.TraceType.NACK: + return 'nack'; + case FbsConsumer.TraceType.PLI: + return 'pli'; + case FbsConsumer.TraceType.RTP: + return 'rtp'; + default: + throw new TypeError(`invalid TraceType: ${traceType}`); + } +} + +function parseConsumerLayers(data: FbsConsumer.ConsumerLayers): ConsumerLayers +{ + const spatialLayer = data.spatialLayer(); + const temporalLayer = data.temporalLayer() !== null ? data.temporalLayer()! : undefined; + + return { + spatialLayer, + temporalLayer + }; +} + +function parseRtpStreamParameters(data: FbsRtpStream.Params): RtpStreamParameters +{ + return { + encodingIdx : data.encodingIdx(), + ssrc : data.ssrc(), + payloadType : data.payloadType(), + mimeType : data.mimeType()!, + clockRate : data.clockRate(), + rid : data.rid()!.length > 0 ? data.rid()! : undefined, + cname : data.cname()!, + rtxSsrc : data.rtxSsrc() !== null ? data.rtxSsrc()! : undefined, + rtxPayloadType : data.rtxPayloadType() !== null ? data.rtxPayloadType()! : undefined, + useNack : data.useNack(), + usePli : data.usePli(), + useFir : data.useFir(), + useInBandFec : data.useInBandFec(), + useDtx : data.useDtx(), + spatialLayers : data.spatialLayers(), + temporalLayers : data.temporalLayers() + }; +} + +function parseRtxStreamParameters(data: FbsRtxStream.Params): RtxStreamParameters +{ + return { + ssrc : data.ssrc(), + payloadType : data.payloadType(), + mimeType : data.mimeType()!, + clockRate : data.clockRate(), + rrid : data.rrid()!.length > 0 ? data.rrid()! : undefined, + cname : data.cname()! + }; +} + +function parseRtxStream(data: FbsRtxStream.RtxDump): RtxStreamDump +{ + const params = parseRtxStreamParameters(data.params()!); + + return { + params + }; +} + +function parseRtpStream(data: FbsRtpStream.Dump): RtpStreamDump +{ + const params = parseRtpStreamParameters(data.params()!); + + let rtxStream: RtxStreamDump | undefined; + + if (data.rtxStream()) + { + rtxStream = parseRtxStream(data.rtxStream()!); + } + + return { + params, + score : data.score(), + rtxStream + }; +} + +function parseBaseConsumerDump(data: FbsConsumer.BaseConsumerDump): BaseConsumerDump +{ + return { + id : data.id()!, + producerId : data.producerId()!, + kind : data.kind() === FbsRtpParameters.MediaKind.AUDIO ? + 'audio' : + 'video', + rtpParameters : parseRtpParameters(data.rtpParameters()!), + consumableRtpEncodings : data.consumableRtpEncodingsLength() > 0 ? + utils.parseVector(data, 'consumableRtpEncodings', parseRtpEncodingParameters) : + undefined, + traceEventTypes : utils.parseVector(data, 'traceEventTypes'), + supportedCodecPayloadTypes : utils.parseVector(data, 'supportedCodecPayloadTypes'), + paused : data.paused(), + producerPaused : data.producerPaused(), + priority : data.priority() + }; +} + +function parseSimpleConsumerDump(data: FbsConsumer.SimpleConsumerDump): SimpleConsumerDump +{ + const base = parseBaseConsumerDump(data.base()!); + const rtpStream = parseRtpStream(data.rtpStream()!); + + return { + ...base, + type : 'simple', + rtpStream + }; +} + +function parseSimulcastConsumerDump( + data: FbsConsumer.SimulcastConsumerDump +) : SimulcastConsumerDump +{ + const base = parseBaseConsumerDump(data.base()!); + const rtpStream = parseRtpStream(data.rtpStream()!); + + return { + ...base, + type : 'simulcast', + rtpStream, + preferredSpatialLayer : data.preferredSpatialLayer(), + targetSpatialLayer : data.targetSpatialLayer(), + currentSpatialLayer : data.currentSpatialLayer(), + preferredTemporalLayer : data.preferredTemporalLayer(), + targetTemporalLayer : data.targetTemporalLayer(), + currentTemporalLayer : data.currentTemporalLayer() + }; +} + +function parseSvcConsumerDump( + data: FbsConsumer.SvcConsumerDump +) : SvcConsumerDump +{ + const dump = parseSimulcastConsumerDump(data); + + dump.type = 'svc'; + + return dump; +} + +function parsePipeConsumerDump( + data: FbsConsumer.PipeConsumerDump +) : PipeConsumerDump +{ + const base = parseBaseConsumerDump(data.base()!); + const rtpStreams = utils.parseVector(data, 'rtpStreams', parseRtpStream); + + return { + ...base, + type : 'pipe', + rtpStreams + }; +} + +function parseConsumerDumpResponse(data: FbsConsumer.DumpResponse): ConsumerDump +{ + switch (data.type()) + { + case FbsRtpParametersType.SIMPLE: + { + const dump = new FbsConsumer.SimpleConsumerDump(); + + data.data(dump); + + return parseSimpleConsumerDump(dump); + } + + case FbsRtpParametersType.SIMULCAST: + { + const dump = new FbsConsumer.SimulcastConsumerDump(); + + data.data(dump); + + return parseSimulcastConsumerDump(dump); + } + + case FbsRtpParametersType.SVC: + { + const dump = new FbsConsumer.SvcConsumerDump(); + + data.data(dump); + + return parseSvcConsumerDump(dump); + } + + case FbsRtpParametersType.PIPE: + { + const dump = new FbsConsumer.PipeConsumerDump(); + + data.data(dump); + + return parsePipeConsumerDump(dump); + } + + default: + { + throw new TypeError(`invalid Consumer type: ${data.type()}`); + } } } + +function parseConsumerStats(binary: FbsConsumer.GetStatsResponse) + : Array +{ + return utils.parseVector(binary, 'stats', parseRtpStreamStats); +} diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index a85413c38f..fae9f463f8 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -1,10 +1,13 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { Channel } from './Channel'; -import { PayloadChannel } from './PayloadChannel'; import { TransportInternal } from './Transport'; -import { SctpStreamParameters } from './SctpParameters'; +import { parseSctpStreamParameters, SctpStreamParameters } from './SctpParameters'; import { AppData } from './types'; +import { Event, Notification } from './fbs/notification'; +import * as FbsTransport from './fbs/transport'; +import * as FbsRequest from './fbs/request'; +import * as FbsDataConsumer from './fbs/data-consumer'; export type DataConsumerOptions = { @@ -76,6 +79,10 @@ export type DataConsumerObserverEvents = close: []; }; +type DataConsumerDump = DataConsumerData & { + id: string; +}; + type DataConsumerInternal = TransportInternal & { dataConsumerId: string; @@ -104,9 +111,6 @@ export class DataConsumer // Channel instance. readonly #channel: Channel; - // PayloadChannel instance. - readonly #payloadChannel: PayloadChannel; - // Closed flag. #closed = false; @@ -124,14 +128,12 @@ export class DataConsumer internal, data, channel, - payloadChannel, appData }: { internal: DataConsumerInternal; data: DataConsumerData; channel: Channel; - payloadChannel: PayloadChannel; appData?: DataConsumerAppData; } ) @@ -143,7 +145,6 @@ export class DataConsumer this.#internal = internal; this.#data = data; this.#channel = channel; - this.#payloadChannel = payloadChannel; this.#appData = appData || {} as DataConsumerAppData; this.handleWorkerNotifications(); @@ -245,12 +246,18 @@ export class DataConsumer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.dataConsumerId); - this.#payloadChannel.removeAllListeners(this.#internal.dataConsumerId); - const reqData = { dataConsumerId: this.#internal.dataConsumerId }; + /* Build Request. */ + const requestOffset = new FbsTransport.CloseDataConsumerRequestT( + this.#internal.dataConsumerId + ).pack(this.#channel.bufferBuilder); - this.#channel.request('transport.closeDataConsumer', this.#internal.transportId, reqData) - .catch(() => {}); + this.#channel.request( + FbsRequest.Method.TRANSPORT_CLOSE_DATA_CONSUMER, + FbsRequest.Body.FBS_Transport_CloseDataConsumerRequest, + requestOffset, + this.#internal.transportId + ).catch(() => {}); this.emit('@close'); @@ -276,7 +283,6 @@ export class DataConsumer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.dataConsumerId); - this.#payloadChannel.removeAllListeners(this.#internal.dataConsumerId); this.safeEmit('transportclose'); @@ -287,11 +293,23 @@ export class DataConsumer /** * Dump DataConsumer. */ - async dump(): Promise + async dump(): Promise { logger.debug('dump()'); - return this.#channel.request('dataConsumer.dump', this.#internal.dataConsumerId); + const response = await this.#channel.request( + FbsRequest.Method.DATA_CONSUMER_DUMP, + undefined, + undefined, + this.#internal.dataConsumerId + ); + + /* Decode Response. */ + const dumpResponse = new FbsDataConsumer.DumpResponse(); + + response.body(dumpResponse); + + return parseDataConsumerDump(dumpResponse); } /** @@ -301,7 +319,19 @@ export class DataConsumer { logger.debug('getStats()'); - return this.#channel.request('dataConsumer.getStats', this.#internal.dataConsumerId); + const response = await this.#channel.request( + FbsRequest.Method.DATA_CONSUMER_GET_STATS, + undefined, + undefined, + this.#internal.dataConsumerId + ); + + /* Decode Response. */ + const data = new FbsDataConsumer.GetStatsResponse(); + + response.body(data); + + return [ parseDataConsumerStats(data) ]; } /** @@ -311,10 +341,16 @@ export class DataConsumer { logger.debug('setBufferedAmountLowThreshold() [threshold:%s]', threshold); - const reqData = { threshold }; + /* Build Request. */ + const requestOffset = FbsDataConsumer.SetBufferedAmountLowThresholdRequest. + createSetBufferedAmountLowThresholdRequest(this.#channel.bufferBuilder, threshold); await this.#channel.request( - 'dataConsumer.setBufferedAmountLowThreshold', this.#internal.dataConsumerId, reqData); + FbsRequest.Method.DATA_CONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD, + FbsRequest.Body.FBS_DataConsumer_SetBufferedAmountLowThresholdRequest, + requestOffset, + this.#internal.dataConsumerId + ); } /** @@ -360,10 +396,38 @@ export class DataConsumer message = Buffer.alloc(1); } - const requestData = String(ppid); + const builder = this.#channel.bufferBuilder; + + let dataOffset = 0; + + if (typeof message === 'string') + { + const messageOffset = builder.createString(message); + + dataOffset = FbsDataConsumer.String.createString(builder, messageOffset); + } + else + { + const messageOffset = FbsDataConsumer.Binary.createValueVector(builder, message); + + dataOffset = FbsDataConsumer.Binary.createBinary(builder, messageOffset); + } - await this.#payloadChannel.request( - 'dataConsumer.send', this.#internal.dataConsumerId, requestData, message); + const requestOffset = FbsDataConsumer.SendRequest.createSendRequest( + builder, + ppid, + typeof message === 'string' ? + FbsDataConsumer.Data.String : + FbsDataConsumer.Data.Binary, + dataOffset + ); + + await this.#channel.request( + FbsRequest.Method.DATA_CONSUMER_SEND, + FbsRequest.Body.FBS_DataConsumer_SendRequest, + requestOffset, + this.#internal.dataConsumerId + ); } /** @@ -373,19 +437,27 @@ export class DataConsumer { logger.debug('getBufferedAmount()'); - const { bufferedAmount } = - await this.#channel.request('dataConsumer.getBufferedAmount', this.#internal.dataConsumerId); + const response = await this.#channel.request( + FbsRequest.Method.DATA_CONSUMER_GET_BUFFERED_AMOUNT, + undefined, + undefined, + this.#internal.dataConsumerId + ); + + const data = new FbsDataConsumer.GetBufferedAmountResponse(); - return bufferedAmount; + response.body(data); + + return data.bufferedAmount(); } private handleWorkerNotifications(): void { - this.#channel.on(this.#internal.dataConsumerId, (event: string, data: any) => + this.#channel.on(this.#internal.dataConsumerId, (event: Event, data?: Notification) => { switch (event) { - case 'dataproducerclose': + case Event.DATACONSUMER_DATAPRODUCER_CLOSE: { if (this.#closed) { @@ -396,7 +468,6 @@ export class DataConsumer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.dataConsumerId); - this.#payloadChannel.removeAllListeners(this.#internal.dataConsumerId); this.emit('@dataproducerclose'); this.safeEmit('dataproducerclose'); @@ -407,55 +478,82 @@ export class DataConsumer break; } - case 'sctpsendbufferfull': + case Event.DATACONSUMER_SCTP_SENDBUFFER_FULL: { this.safeEmit('sctpsendbufferfull'); break; } - case 'bufferedamountlow': + case Event.DATACONSUMER_BUFFERED_AMOUNT_LOW: { - const { bufferedAmount } = data as { bufferedAmount: number }; + const notification = new FbsDataConsumer.BufferedAmountLowNotification(); + + data!.body(notification); + + const bufferedAmount = notification.bufferedAmount(); this.safeEmit('bufferedamountlow', bufferedAmount); break; } - default: - { - logger.error('ignoring unknown event "%s" in channel listener', event); - } - } - }); - - this.#payloadChannel.on( - this.#internal.dataConsumerId, - (event: string, data: any | undefined, payload: Buffer) => - { - switch (event) + case Event.DATACONSUMER_MESSAGE: { - case 'message': + if (this.#closed) { - if (this.#closed) - { - break; - } + break; + } - const ppid = data.ppid as number; - const message = payload; + const notification = new FbsDataConsumer.MessageNotification(); - this.safeEmit('message', message, ppid); + data!.body(notification); - break; - } + this.safeEmit( + 'message', + Buffer.from(notification.dataArray()!), + notification.ppid() + ); - default: - { - logger.error('ignoring unknown event "%s" in payload channel listener', event); - } + break; } - }); + + default: + { + logger.error('ignoring unknown event "%s" in channel listener', event); + } + } + }); } } + +export function parseDataConsumerDump( + data: FbsDataConsumer.DumpResponse +): DataConsumerDump +{ + return { + id : data.id()!, + dataProducerId : data.dataProducerId()!, + type : data.type()! as DataConsumerType, + sctpStreamParameters : data.sctpStreamParameters() !== null ? + parseSctpStreamParameters(data.sctpStreamParameters()!) : + undefined, + label : data.label()!, + protocol : data.protocol()! + }; +} + +function parseDataConsumerStats( + binary: FbsDataConsumer.GetStatsResponse +):DataConsumerStat +{ + return { + type : 'data-consumer', + timestamp : Number(binary.timestamp()), + label : binary.label()!, + protocol : binary.protocol()!, + messagesSent : Number(binary.messagesSent()), + bytesSent : Number(binary.bytesSent()), + bufferedAmount : binary.bufferedAmount() + }; +} diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index 94320ab26d..baeea34938 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -1,10 +1,13 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { Channel } from './Channel'; -import { PayloadChannel } from './PayloadChannel'; import { TransportInternal } from './Transport'; -import { SctpStreamParameters } from './SctpParameters'; +import { parseSctpStreamParameters, SctpStreamParameters } from './SctpParameters'; import { AppData } from './types'; +import * as FbsTransport from './fbs/transport'; +import * as FbsNotification from './fbs/notification'; +import * as FbsRequest from './fbs/request'; +import * as FbsDataProducer from './fbs/data-producer'; export type DataProducerOptions = { @@ -62,6 +65,10 @@ export type DataProducerObserverEvents = close: []; }; +type DataProducerDump = DataProducerData & { + id: string; +}; + type DataProducerInternal = TransportInternal & { dataProducerId: string; @@ -89,9 +96,6 @@ export class DataProducer // Channel instance. readonly #channel: Channel; - // PayloadChannel instance. - readonly #payloadChannel: PayloadChannel; - // Closed flag. #closed = false; @@ -109,14 +113,12 @@ export class DataProducer internal, data, channel, - payloadChannel, appData }: { internal: DataProducerInternal; data: DataProducerData; channel: Channel; - payloadChannel: PayloadChannel; appData?: DataProducerAppData; } ) @@ -128,7 +130,6 @@ export class DataProducer this.#internal = internal; this.#data = data; this.#channel = channel; - this.#payloadChannel = payloadChannel; this.#appData = appData || {} as DataProducerAppData; this.handleWorkerNotifications(); @@ -222,12 +223,18 @@ export class DataProducer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.dataProducerId); - this.#payloadChannel.removeAllListeners(this.#internal.dataProducerId); - const reqData = { dataProducerId: this.#internal.dataProducerId }; + /* Build Request. */ + const requestOffset = new FbsTransport.CloseDataProducerRequestT( + this.#internal.dataProducerId + ).pack(this.#channel.bufferBuilder); - this.#channel.request('transport.closeDataProducer', this.#internal.transportId, reqData) - .catch(() => {}); + this.#channel.request( + FbsRequest.Method.TRANSPORT_CLOSE_DATA_PRODUCER, + FbsRequest.Body.FBS_Transport_CloseDataProducerRequest, + requestOffset, + this.#internal.transportId + ).catch(() => {}); this.emit('@close'); @@ -253,7 +260,6 @@ export class DataProducer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.dataProducerId); - this.#payloadChannel.removeAllListeners(this.#internal.dataProducerId); this.safeEmit('transportclose'); @@ -264,11 +270,23 @@ export class DataProducer /** * Dump DataProducer. */ - async dump(): Promise + async dump(): Promise { logger.debug('dump()'); - return this.#channel.request('dataProducer.dump', this.#internal.dataProducerId); + const response = await this.#channel.request( + FbsRequest.Method.DATA_PRODUCER_DUMP, + undefined, + undefined, + this.#internal.dataProducerId + ); + + /* Decode Response. */ + const produceResponse = new FbsDataProducer.DumpResponse(); + + response.body(produceResponse); + + return parseDataProducerDump(produceResponse); } /** @@ -278,7 +296,19 @@ export class DataProducer { logger.debug('getStats()'); - return this.#channel.request('dataProducer.getStats', this.#internal.dataProducerId); + const response = await this.#channel.request( + FbsRequest.Method.DATA_PRODUCER_GET_STATS, + undefined, + undefined, + this.#internal.dataProducerId + ); + + /* Decode Response. */ + const data = new FbsDataProducer.GetStatsResponse(); + + response.body(data); + + return [ parseDataProducerStats(data) ]; } /** @@ -324,10 +354,38 @@ export class DataProducer message = Buffer.alloc(1); } - const notifData = String(ppid); + let dataOffset = 0; + + const builder = this.#channel.bufferBuilder; + + if (typeof message === 'string') + { + const messageOffset = builder.createString(message); - this.#payloadChannel.notify( - 'dataProducer.send', this.#internal.dataProducerId, notifData, message); + dataOffset = FbsDataProducer.String.createString(builder, messageOffset); + } + else + { + const messageOffset = FbsDataProducer.Binary.createValueVector(builder, message); + + dataOffset = FbsDataProducer.Binary.createBinary(builder, messageOffset); + } + + const notificationOffset = FbsDataProducer.SendNotification.createSendNotification( + builder, + ppid, + typeof message === 'string' ? + FbsDataProducer.Data.String : + FbsDataProducer.Data.Binary, + dataOffset + ); + + this.#channel.notify( + FbsNotification.Event.DATA_PRODUCER_SEND, + FbsNotification.Body.FBS_DataProducer_SendNotification, + notificationOffset, + this.#internal.dataProducerId + ); } private handleWorkerNotifications(): void @@ -335,3 +393,32 @@ export class DataProducer // No need to subscribe to any event. } } + +export function parseDataProducerDump( + data: FbsDataProducer.DumpResponse +): DataProducerDump +{ + return { + id : data.id()!, + type : data.type()! as DataProducerType, + sctpStreamParameters : data.sctpStreamParameters() !== null ? + parseSctpStreamParameters(data.sctpStreamParameters()!) : + undefined, + label : data.label()!, + protocol : data.protocol()! + }; +} + +function parseDataProducerStats( + binary: FbsDataProducer.GetStatsResponse +):DataProducerStat +{ + return { + type : 'data-producer', + timestamp : Number(binary.timestamp()), + label : binary.label()!, + protocol : binary.protocol()!, + messagesReceived : Number(binary.messagesReceived()), + bytesReceived : Number(binary.bytesReceived()) + }; +} diff --git a/node/src/DirectTransport.ts b/node/src/DirectTransport.ts index f4bc0be37a..45573fc589 100644 --- a/node/src/DirectTransport.ts +++ b/node/src/DirectTransport.ts @@ -1,14 +1,23 @@ import { Logger } from './Logger'; import { UnsupportedError } from './errors'; import { + BaseTransportDump, + BaseTransportStats, + parseBaseTransportDump, + parseBaseTransportStats, + parseTransportTraceEventData, Transport, - TransportTraceEventData, TransportEvents, TransportObserverEvents, TransportConstructorOptions } from './Transport'; import { SctpParameters } from './SctpParameters'; import { AppData } from './types'; +import { Event, Notification } from './fbs/notification'; +import * as FbsDirectTransport from './fbs/direct-transport'; +import * as FbsTransport from './fbs/transport'; +import * as FbsNotification from './fbs/notification'; +import * as FbsRequest from './fbs/request'; export type DirectTransportOptions = { @@ -24,29 +33,9 @@ export type DirectTransportOptions super.routerClosed(); } + /** + * Dump Transport. + */ + async dump(): Promise + { + logger.debug('dump()'); + + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_DUMP, + undefined, + undefined, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsDirectTransport.DumpResponse(); + + response.body(data); + + return parseDirectTransportDumpResponse(data); + } + /** * Get DirectTransport stats. * @@ -135,7 +146,19 @@ export class DirectTransport { logger.debug('getStats()'); - return this.channel.request('transport.getStats', this.internal.transportId); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_GET_STATS, + undefined, + undefined, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsDirectTransport.GetStatsResponse(); + + response.body(data); + + return [ parseGetStatsResponse(data) ]; } /** @@ -188,19 +211,37 @@ export class DirectTransport throw new TypeError('rtcpPacket must be a Buffer'); } - this.payloadChannel.notify( - 'transport.sendRtcp', this.internal.transportId, undefined, rtcpPacket); + const builder = this.channel.bufferBuilder; + const dataOffset = + FbsTransport.SendRtcpNotification.createDataVector(builder, rtcpPacket); + const notificationOffset = + FbsTransport.SendRtcpNotification.createSendRtcpNotification( + builder, + dataOffset + ); + + this.channel.notify( + FbsNotification.Event.TRANSPORT_SEND_RTCP, + FbsNotification.Body.FBS_Transport_SendRtcpNotification, + notificationOffset, + this.internal.transportId + ); + } private handleWorkerNotifications(): void { - this.channel.on(this.internal.transportId, (event: string, data?: any) => + this.channel.on(this.internal.transportId, (event: Event, data?: Notification) => { switch (event) { - case 'trace': + case Event.TRANSPORT_TRACE: { - const trace = data as TransportTraceEventData; + const notification = new FbsTransport.TraceNotification(); + + data!.body(notification); + + const trace = parseTransportTraceEventData(notification); this.safeEmit('trace', trace); @@ -210,38 +251,46 @@ export class DirectTransport break; } + case Event.DIRECTTRANSPORT_RTCP: + { + if (this.closed) + { + break; + } + + const notification = new FbsDirectTransport.RtcpNotification(); + + data!.body(notification); + + this.safeEmit('rtcp', Buffer.from(notification.dataArray()!)); + + break; + } + default: { logger.error('ignoring unknown event "%s"', event); } } }); + } +} - this.payloadChannel.on( - this.internal.transportId, - (event: string, data: any | undefined, payload: Buffer) => - { - switch (event) - { - case 'rtcp': - { - if (this.closed) - { - break; - } - - const packet = payload; - - this.safeEmit('rtcp', packet); +export function parseDirectTransportDumpResponse( + binary: FbsDirectTransport.DumpResponse +): BaseTransportDump +{ + return parseBaseTransportDump(binary.base()!); +} - break; - } +function parseGetStatsResponse( + binary: FbsDirectTransport.GetStatsResponse +):DirectTransportStat +{ + const base = parseBaseTransportStats(binary.base()!); - default: - { - logger.error('ignoring unknown event "%s"', event); - } - } - }); - } + return { + ...base, + type : 'direct-transport' + }; } diff --git a/node/src/PayloadChannel.ts b/node/src/PayloadChannel.ts deleted file mode 100644 index d8f8074703..0000000000 --- a/node/src/PayloadChannel.ts +++ /dev/null @@ -1,402 +0,0 @@ -import * as os from 'os'; -import { Duplex } from 'stream'; -import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; -import { InvalidStateError } from './errors'; - -const littleEndian = os.endianness() == 'LE'; -const logger = new Logger('PayloadChannel'); - -type Sent = -{ - id: number; - method: string; - resolve: (data?: any) => void; - reject: (error: Error) => void; - close: () => void; -}; - -// Binary length for a 4194304 bytes payload. -const MESSAGE_MAX_LEN = 4194308; -const PAYLOAD_MAX_LEN = 4194304; - -export class PayloadChannel extends EnhancedEventEmitter -{ - // Closed flag. - #closed = false; - - // Unix Socket instance for sending messages to the worker process. - readonly #producerSocket: Duplex; - - // Unix Socket instance for receiving messages to the worker process. - readonly #consumerSocket: Duplex; - - // Next id for messages sent to the worker process. - #nextId = 0; - - // Map of pending sent requests. - readonly #sents: Map = new Map(); - - // Buffer for reading messages from the worker. - #recvBuffer = Buffer.alloc(0); - - // Ongoing notification (waiting for its payload). - #ongoingNotification?: { targetId: string; event: string; data?: any }; - - /** - * @private - */ - constructor( - { - producerSocket, - consumerSocket - }: - { - producerSocket: any; - consumerSocket: any; - }) - { - super(); - - logger.debug('constructor()'); - - this.#producerSocket = producerSocket as Duplex; - this.#consumerSocket = consumerSocket as Duplex; - - // Read PayloadChannel notifications from the worker. - this.#consumerSocket.on('data', (buffer: Buffer) => - { - if (!this.#recvBuffer.length) - { - this.#recvBuffer = buffer; - } - else - { - this.#recvBuffer = Buffer.concat( - [ this.#recvBuffer, buffer ], - this.#recvBuffer.length + buffer.length); - } - - if (this.#recvBuffer.length > PAYLOAD_MAX_LEN) - { - logger.error('receiving buffer is full, discarding all data in it'); - - // Reset the buffer and exit. - this.#recvBuffer = Buffer.alloc(0); - - return; - } - - let msgStart = 0; - - while (true) // eslint-disable-line no-constant-condition - { - const readLen = this.#recvBuffer.length - msgStart; - - if (readLen < 4) - { - // Incomplete data. - break; - } - - const dataView = new DataView( - this.#recvBuffer.buffer, - this.#recvBuffer.byteOffset + msgStart); - const msgLen = dataView.getUint32(0, littleEndian); - - if (readLen < 4 + msgLen) - { - // Incomplete data. - break; - } - - const payload = this.#recvBuffer.subarray(msgStart + 4, msgStart + 4 + msgLen); - - msgStart += 4 + msgLen; - - this.processData(payload); - } - - if (msgStart != 0) - { - this.#recvBuffer = this.#recvBuffer.slice(msgStart); - } - }); - - this.#consumerSocket.on('end', () => ( - logger.debug('Consumer PayloadChannel ended by the worker process') - )); - - this.#consumerSocket.on('error', (error) => ( - logger.error('Consumer PayloadChannel error: %s', String(error)) - )); - - this.#producerSocket.on('end', () => ( - logger.debug('Producer PayloadChannel ended by the worker process') - )); - - this.#producerSocket.on('error', (error) => ( - logger.error('Producer PayloadChannel error: %s', String(error)) - )); - } - - /** - * @private - */ - close(): void - { - if (this.#closed) - { - return; - } - - logger.debug('close()'); - - this.#closed = true; - - // Remove event listeners but leave a fake 'error' handler to avoid - // propagation. - this.#consumerSocket.removeAllListeners('end'); - this.#consumerSocket.removeAllListeners('error'); - this.#consumerSocket.on('error', () => {}); - - this.#producerSocket.removeAllListeners('end'); - this.#producerSocket.removeAllListeners('error'); - this.#producerSocket.on('error', () => {}); - - // Destroy the socket after a while to allow pending incoming messages. - setTimeout(() => - { - try { this.#producerSocket.destroy(); } - catch (error) {} - try { this.#consumerSocket.destroy(); } - catch (error) {} - }, 200); - } - - /** - * @private - */ - notify( - event: string, - handlerId: string, - data: string | undefined, - payload: string | Buffer - ): void - { - logger.debug('notify() [event:%s]', event); - - if (this.#closed) - { - throw new InvalidStateError('PayloadChannel closed'); - } - - const notification = `n:${event}:${handlerId}:${data}`; - - if (Buffer.byteLength(notification) > MESSAGE_MAX_LEN) - { - throw new Error('PayloadChannel notification too big'); - } - else if (Buffer.byteLength(payload) > MESSAGE_MAX_LEN) - { - throw new Error('PayloadChannel payload too big'); - } - - try - { - // This may throw if closed or remote side ended. - this.#producerSocket.write( - Buffer.from(Uint32Array.of(Buffer.byteLength(notification)).buffer)); - this.#producerSocket.write(notification); - } - catch (error) - { - logger.warn('notify() | sending notification failed: %s', String(error)); - - return; - } - - try - { - // This may throw if closed or remote side ended. - this.#producerSocket.write( - Buffer.from(Uint32Array.of(Buffer.byteLength(payload)).buffer)); - this.#producerSocket.write(payload); - } - catch (error) - { - logger.warn('notify() | sending payload failed: %s', String(error)); - - return; - } - } - - /** - * @private - */ - async request( - method: string, - handlerId: string, - data: string, - payload: string | Buffer): Promise - { - this.#nextId < 4294967295 ? ++this.#nextId : (this.#nextId = 1); - - const id = this.#nextId; - - logger.debug('request() [method:%s, id:%s]', method, id); - - if (this.#closed) - { - throw new InvalidStateError('PayloadChannel closed'); - } - - const request = `r:${id}:${method}:${handlerId}:${data}`; - - if (Buffer.byteLength(request) > MESSAGE_MAX_LEN) - { - throw new Error('PayloadChannel request too big'); - } - else if (Buffer.byteLength(payload) > MESSAGE_MAX_LEN) - { - throw new Error('PayloadChannel payload too big'); - } - - // This may throw if closed or remote side ended. - this.#producerSocket.write( - Buffer.from(Uint32Array.of(Buffer.byteLength(request)).buffer)); - this.#producerSocket.write(request); - this.#producerSocket.write( - Buffer.from(Uint32Array.of(Buffer.byteLength(payload)).buffer)); - this.#producerSocket.write(payload); - - return new Promise((pResolve, pReject) => - { - const sent: Sent = - { - id : id, - method : method, - resolve : (data2) => - { - if (!this.#sents.delete(id)) - { - return; - } - - pResolve(data2); - }, - reject : (error) => - { - if (!this.#sents.delete(id)) - { - return; - } - - pReject(error); - }, - close : () => - { - pReject(new InvalidStateError('PayloadChannel closed')); - } - }; - - // Add sent stuff to the map. - this.#sents.set(id, sent); - }); - } - - private processData(data: Buffer): void - { - if (!this.#ongoingNotification) - { - let msg; - - try - { - msg = JSON.parse(data.toString('utf8')); - } - catch (error) - { - logger.error( - 'received invalid data from the worker process: %s', - String(error)); - - return; - } - - // If a response, retrieve its associated request. - if (msg.id) - { - const sent = this.#sents.get(msg.id); - - if (!sent) - { - logger.error( - 'received response does not match any sent request [id:%s]', msg.id); - - return; - } - - if (msg.accepted) - { - logger.debug( - 'request succeeded [method:%s, id:%s]', sent.method, sent.id); - - sent.resolve(msg.data); - } - else if (msg.error) - { - logger.warn( - 'request failed [method:%s, id:%s]: %s', - sent.method, sent.id, msg.reason); - - switch (msg.error) - { - case 'TypeError': - sent.reject(new TypeError(msg.reason)); - break; - - default: - sent.reject(new Error(msg.reason)); - } - } - else - { - logger.error( - 'received response is not accepted nor rejected [method:%s, id:%s]', - sent.method, sent.id); - } - } - // If a notification, create the ongoing notification instance. - else if (msg.targetId && msg.event) - { - this.#ongoingNotification = - { - targetId : String(msg.targetId), - event : msg.event, - data : msg.data - }; - } - else - { - logger.error('received data is not a notification nor a response'); - - return; - } - } - else - { - const payload = data as Buffer; - - // Emit the corresponding event. - this.emit( - this.#ongoingNotification.targetId, - this.#ongoingNotification.event, - this.#ongoingNotification.data, - payload); - - // Unset ongoing notification. - this.#ongoingNotification = undefined; - } - } -} diff --git a/node/src/PipeTransport.ts b/node/src/PipeTransport.ts index f312a79ec6..5f19519a49 100644 --- a/node/src/PipeTransport.ts +++ b/node/src/PipeTransport.ts @@ -1,20 +1,39 @@ import { v4 as uuidv4 } from 'uuid'; +import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; import * as ortc from './ortc'; import { + BaseTransportDump, + BaseTransportStats, + parseBaseTransportDump, + parseBaseTransportStats, + fbsSctpState2StcpState, + parseTuple, + parseTransportTraceEventData, Transport, TransportListenIp, TransportTuple, - TransportTraceEventData, TransportEvents, TransportObserverEvents, TransportConstructorOptions, SctpState } from './Transport'; import { Consumer, ConsumerType } from './Consumer'; +import { Producer } from './Producer'; +import { RtpParameters, serializeRtpEncodingParameters, serializeRtpParameters } from './RtpParameters'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; -import { SrtpParameters } from './SrtpParameters'; +import { + parseSrtpParameters, + serializeSrtpParameters, + SrtpParameters +} from './SrtpParameters'; import { AppData } from './types'; +import { MediaKind as FbsMediaKind } from './fbs/rtp-parameters/media-kind'; +import * as FbsRtpParameters from './fbs/rtp-parameters'; +import { Event, Notification } from './fbs/notification'; +import * as FbsRequest from './fbs/request'; +import * as FbsTransport from './fbs/transport'; +import * as FbsPipeTransport from './fbs/pipe-transport'; export type PipeTransportOptions = { @@ -71,31 +90,9 @@ export type PipeTransportOptions appData?: PipeTransportAppData; }; -export type PipeTransportStat = +export type PipeTransportStat = BaseTransportStats & { - // Common to all Transports. type: string; - transportId: string; - timestamp: number; - sctpState?: SctpState; - bytesReceived: number; - recvBitrate: number; - bytesSent: number; - sendBitrate: number; - rtpBytesReceived: number; - rtpRecvBitrate: number; - rtpBytesSent: number; - rtpSendBitrate: number; - rtxBytesReceived: number; - rtxRecvBitrate: number; - rtxBytesSent: number; - rtxSendBitrate: number; - probationBytesSent: number; - probationSendBitrate: number; - availableOutgoingBitrate?: number; - availableIncomingBitrate?: number; - maxIncomingBitrate?: number; - // PipeTransport specific. tuple: TransportTuple; }; @@ -137,6 +134,13 @@ export type PipeTransportData = srtpParameters?: SrtpParameters; }; +export type PipeTransportDump = BaseTransportDump & +{ + tuple: TransportTuple; + rtx: boolean; + srtpParameters?: SrtpParameters; +}; + const logger = new Logger('PipeTransport'); export class PipeTransport @@ -250,7 +254,19 @@ export class PipeTransport { logger.debug('getStats()'); - return this.channel.request('transport.getStats', this.internal.transportId); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_GET_STATS, + undefined, + undefined, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsPipeTransport.GetStatsResponse(); + + response.body(data); + + return [ parseGetStatsResponse(data) ]; } /** @@ -273,13 +289,31 @@ export class PipeTransport { logger.debug('connect()'); - const reqData = { ip, port, srtpParameters }; + const requestOffset = createConnectRequest({ + builder : this.channel.bufferBuilder, + ip, + port, + srtpParameters + }); - const data = - await this.channel.request('transport.connect', this.internal.transportId, reqData); + // Wait for response. + const response = await this.channel.request( + FbsRequest.Method.PIPE_TRANSPORT_CONNECT, + FbsRequest.Body.FBS_PipeTransport_ConnectRequest, + requestOffset, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsPipeTransport.ConnectResponse(); + + response.body(data); // Update data. - this.#data.tuple = data.tuple; + if (data.tuple()) + { + this.#data.tuple = parseTuple(data.tuple()!); + } } /** @@ -320,18 +354,28 @@ export class PipeTransport } ); - const reqData = - { - consumerId : uuidv4(), - producerId, - kind : producer.kind, - rtpParameters, - type : 'pipe', - consumableRtpEncodings : producer.consumableRtpParameters.encodings - }; + const consumerId = uuidv4(); - const status = - await this.channel.request('transport.consume', this.internal.transportId, reqData); + const consumeRequestOffset = createConsumeRequest({ + builder : this.channel.bufferBuilder, + consumerId, + producer, + rtpParameters + }); + + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_CONSUME, + FbsRequest.Body.FBS_Transport_ConsumeRequest, + consumeRequestOffset, + this.internal.transportId + ); + + /* Decode Response. */ + const consumeResponse = new FbsTransport.ConsumeResponse(); + + response.body(consumeResponse); + + const status = consumeResponse.unpack(); const data = { @@ -346,11 +390,10 @@ export class PipeTransport internal : { ...this.internal, - consumerId : reqData.consumerId + consumerId }, data, channel : this.channel, - payloadChannel : this.payloadChannel, appData, paused : status.paused, producerPaused : status.producerPaused @@ -368,13 +411,17 @@ export class PipeTransport private handleWorkerNotifications(): void { - this.channel.on(this.internal.transportId, (event: string, data?: any) => + this.channel.on(this.internal.transportId, (event: Event, data?: Notification) => { switch (event) { - case 'sctpstatechange': + case Event.TRANSPORT_SCTP_STATE_CHANGE: { - const sctpState = data.sctpState as SctpState; + const notification = new FbsTransport.SctpStateChangeNotification(); + + data!.body(notification); + + const sctpState = fbsSctpState2StcpState(notification.sctpState()); this.#data.sctpState = sctpState; @@ -386,9 +433,13 @@ export class PipeTransport break; } - case 'trace': + case Event.TRANSPORT_TRACE: { - const trace = data as TransportTraceEventData; + const notification = new FbsTransport.TraceNotification(); + + data!.body(notification); + + const trace = parseTransportTraceEventData(notification); this.safeEmit('trace', trace); @@ -406,3 +457,143 @@ export class PipeTransport }); } } + +/* + * flatbuffers helpers. + */ + +export function parsePipeTransportDumpResponse( + binary: FbsPipeTransport.DumpResponse +): PipeTransportDump +{ + // Retrieve BaseTransportDump. + const baseTransportDump = parseBaseTransportDump(binary.base()!); + // Retrieve RTP Tuple. + const tuple = parseTuple(binary.tuple()!); + + // Retrieve SRTP Parameters. + let srtpParameters: SrtpParameters | undefined; + + if (binary.srtpParameters()) + { + srtpParameters = parseSrtpParameters(binary.srtpParameters()!); + } + + return { + ...baseTransportDump, + tuple : tuple, + rtx : binary.rtx(), + srtpParameters : srtpParameters + }; +} + +function parseGetStatsResponse( + binary: FbsPipeTransport.GetStatsResponse +):PipeTransportStat +{ + const base = parseBaseTransportStats(binary.base()!); + + return { + ...base, + type : 'pipe-transport', + tuple : parseTuple(binary.tuple()!) + }; +} + +function createConsumeRequest({ + builder, + consumerId, + producer, + rtpParameters +} : { + builder: flatbuffers.Builder; + consumerId: string; + producer: Producer; + rtpParameters: RtpParameters; +}): number +{ + // Build the request. + const producerIdOffset = builder.createString(producer.id); + const consumerIdOffset = builder.createString(consumerId); + const rtpParametersOffset = serializeRtpParameters(builder, rtpParameters); + let consumableRtpEncodingsOffset: number | undefined; + + if (producer.consumableRtpParameters.encodings) + { + consumableRtpEncodingsOffset = serializeRtpEncodingParameters( + builder, producer.consumableRtpParameters.encodings + ); + } + + const ConsumeRequest = FbsTransport.ConsumeRequest; + + // Create Consume Request. + ConsumeRequest.startConsumeRequest(builder); + ConsumeRequest.addConsumerId(builder, consumerIdOffset); + ConsumeRequest.addProducerId(builder, producerIdOffset); + ConsumeRequest.addKind( + builder, producer.kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO); + ConsumeRequest.addRtpParameters(builder, rtpParametersOffset); + ConsumeRequest.addType(builder, FbsRtpParameters.Type.PIPE); + + if (consumableRtpEncodingsOffset) + { + ConsumeRequest.addConsumableRtpEncodings(builder, consumableRtpEncodingsOffset); + } + + return ConsumeRequest.endConsumeRequest(builder); +} + +function createConnectRequest( + { + builder, + ip, + port, + srtpParameters + }: + { + builder: flatbuffers.Builder; + ip?: string; + port?: number; + srtpParameters?: SrtpParameters; + } +): number +{ + try + { + let ipOffset = 0; + let srtpParametersOffset = 0; + + if (ip) + { + ipOffset = builder.createString(ip); + } + + // Serialize SrtpParameters. + if (srtpParameters) + { + srtpParametersOffset = serializeSrtpParameters(builder, srtpParameters); + } + + // Create PlainTransportConnectData. + FbsPipeTransport.ConnectRequest.startConnectRequest(builder); + FbsPipeTransport.ConnectRequest.addIp(builder, ipOffset); + + if (typeof port === 'number') + { + FbsPipeTransport.ConnectRequest.addPort(builder, port); + } + if (srtpParameters) + { + FbsPipeTransport.ConnectRequest.addSrtpParameters( + builder, srtpParametersOffset + ); + } + + return FbsPipeTransport.ConnectRequest.endConnectRequest(builder); + } + catch (error) + { + throw new TypeError(`${error}`); + } +} diff --git a/node/src/PlainTransport.ts b/node/src/PlainTransport.ts index 23c4e266c0..803442662e 100644 --- a/node/src/PlainTransport.ts +++ b/node/src/PlainTransport.ts @@ -1,17 +1,33 @@ +import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; import { + fbsSctpState2StcpState, + BaseTransportDump, + BaseTransportStats, + parseTuple, + parseBaseTransportDump, + parseBaseTransportStats, + parseTransportTraceEventData, Transport, TransportListenIp, TransportTuple, - TransportTraceEventData, TransportEvents, TransportObserverEvents, TransportConstructorOptions, SctpState } from './Transport'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; -import { SrtpParameters, SrtpCryptoSuite } from './SrtpParameters'; +import { + parseSrtpParameters, + serializeSrtpParameters, + SrtpParameters, + SrtpCryptoSuite +} from './SrtpParameters'; import { AppData } from './types'; +import { Event, Notification } from './fbs/notification'; +import * as FbsRequest from './fbs/request'; +import * as FbsTransport from './fbs/transport'; +import * as FbsPlainTransport from './fbs/plain-transport'; export type PlainTransportOptions = { @@ -79,31 +95,9 @@ export type PlainTransportOptions @@ -255,6 +258,28 @@ export class PlainTransport super.routerClosed(); } + /** + * Dump Transport. + */ + async dump(): Promise + { + logger.debug('dump()'); + + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_DUMP, + undefined, + undefined, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsPlainTransport.DumpResponse(); + + response.body(data); + + return parsePlainTransportDumpResponse(data); + } + /** * Get PlainTransport stats. * @@ -264,7 +289,19 @@ export class PlainTransport { logger.debug('getStats()'); - return this.channel.request('transport.getStats', this.internal.transportId); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_GET_STATS, + undefined, + undefined, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsPlainTransport.GetStatsResponse(); + + response.body(data); + + return [ parseGetStatsResponse(data) ]; } /** @@ -289,34 +326,58 @@ export class PlainTransport { logger.debug('connect()'); - const reqData = { ip, port, rtcpPort, srtpParameters }; + const requestOffset = createConnectRequest({ + builder : this.channel.bufferBuilder, + ip, + port, + rtcpPort, + srtpParameters + }); + + // Wait for response. + const response = await this.channel.request( + FbsRequest.Method.PLAIN_TRANSPORT_CONNECT, + FbsRequest.Body.FBS_PlainTransport_ConnectRequest, + requestOffset, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsPlainTransport.ConnectResponse(); - const data = - await this.channel.request('transport.connect', this.internal.transportId, reqData); + response.body(data); // Update data. - if (data.tuple) + if (data.tuple()) { - this.#data.tuple = data.tuple; + this.#data.tuple = parseTuple(data.tuple()!); } - if (data.rtcpTuple) + if (data.rtcpTuple()) { - this.#data.rtcpTuple = data.rtcpTuple; + this.#data.rtcpTuple = parseTuple(data.rtcpTuple()!); } - this.#data.srtpParameters = data.srtpParameters; + if (data.srtpParameters()) + { + this.#data.srtpParameters = parseSrtpParameters( + data.srtpParameters()!); + } } private handleWorkerNotifications(): void { - this.channel.on(this.internal.transportId, (event: string, data?: any) => + this.channel.on(this.internal.transportId, (event: Event, data?: Notification) => { switch (event) { - case 'tuple': + case Event.PLAINTRANSPORT_TUPLE: { - const tuple = data.tuple as TransportTuple; + const notification = new FbsPlainTransport.TupleNotification(); + + data!.body(notification); + + const tuple = parseTuple(notification.tuple()!); this.#data.tuple = tuple; @@ -328,9 +389,13 @@ export class PlainTransport break; } - case 'rtcptuple': + case Event.PLAINTRANSPORT_RTCP_TUPLE: { - const rtcpTuple = data.rtcpTuple as TransportTuple; + const notification = new FbsPlainTransport.RtcpTupleNotification(); + + data!.body(notification); + + const rtcpTuple = parseTuple(notification.tuple()!); this.#data.rtcpTuple = rtcpTuple; @@ -342,9 +407,13 @@ export class PlainTransport break; } - case 'sctpstatechange': + case Event.TRANSPORT_SCTP_STATE_CHANGE: { - const sctpState = data.sctpState as SctpState; + const notification = new FbsTransport.SctpStateChangeNotification(); + + data!.body(notification); + + const sctpState = fbsSctpState2StcpState(notification.sctpState()); this.#data.sctpState = sctpState; @@ -356,9 +425,13 @@ export class PlainTransport break; } - case 'trace': + case Event.TRANSPORT_TRACE: { - const trace = data as TransportTraceEventData; + const notification = new FbsTransport.TraceNotification(); + + data!.body(notification); + + const trace = parseTransportTraceEventData(notification); this.safeEmit('trace', trace); @@ -376,3 +449,116 @@ export class PlainTransport }); } } + +export function parsePlainTransportDumpResponse( + binary: FbsPlainTransport.DumpResponse +): PlainTransportDump +{ + // Retrieve BaseTransportDump. + const baseTransportDump = parseBaseTransportDump(binary.base()!); + // Retrieve RTP Tuple. + const tuple = parseTuple(binary.tuple()!); + + // Retrieve RTCP Tuple. + let rtcpTuple: TransportTuple | undefined; + + if (binary.rtcpTuple()) + { + rtcpTuple = parseTuple(binary.rtcpTuple()!); + } + + // Retrieve SRTP Parameters. + let srtpParameters: SrtpParameters | undefined; + + if (binary.srtpParameters()) + { + srtpParameters = parseSrtpParameters(binary.srtpParameters()!); + } + + return { + ...baseTransportDump, + rtcpMux : binary.rtcpMux(), + comedia : binary.comedia(), + tuple : tuple, + rtcpTuple : rtcpTuple, + srtpParameters : srtpParameters + }; +} + +function parseGetStatsResponse( + binary: FbsPlainTransport.GetStatsResponse +):PlainTransportStat +{ + const base = parseBaseTransportStats(binary.base()!); + + return { + ...base, + type : 'plain-rtp-transport', + rtcpMux : binary.rtcpMux(), + comedia : binary.comedia(), + tuple : parseTuple(binary.tuple()!), + rtcpTuple : binary.rtcpTuple() ? + parseTuple(binary.rtcpTuple()!) : + undefined + }; +} + +function createConnectRequest( + { + builder, + ip, + port, + rtcpPort, + srtpParameters + }: + { + builder : flatbuffers.Builder; + ip?: string; + port?: number; + rtcpPort?: number; + srtpParameters?: SrtpParameters; + } +): number +{ + try + { + let ipOffset = 0; + let srtpParametersOffset = 0; + + if (ip) + { + ipOffset = builder.createString(ip); + } + + // Serialize SrtpParameters. + if (srtpParameters) + { + srtpParametersOffset = serializeSrtpParameters(builder, srtpParameters); + } + + // Create PlainTransportConnectData. + FbsPlainTransport.ConnectRequest.startConnectRequest(builder); + FbsPlainTransport.ConnectRequest.addIp(builder, ipOffset); + + if (typeof port === 'number') + { + FbsPlainTransport.ConnectRequest.addPort(builder, port); + } + if (typeof rtcpPort === 'number') + { + FbsPlainTransport.ConnectRequest.addRtcpPort(builder, rtcpPort); + } + if (srtpParameters) + { + FbsPlainTransport.ConnectRequest.addSrtpParameters( + builder, srtpParametersOffset + ); + } + + return FbsPlainTransport.ConnectRequest.endConnectRequest(builder); + } + catch (error) + { + throw new TypeError(`${error}`); + } +} diff --git a/node/src/Producer.ts b/node/src/Producer.ts index 2d152ffb40..93e2d71506 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -1,10 +1,18 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { Channel } from './Channel'; -import { PayloadChannel } from './PayloadChannel'; import { TransportInternal } from './Transport'; -import { MediaKind, RtpParameters } from './RtpParameters'; +import { MediaKind, RtpParameters, parseRtpParameters } from './RtpParameters'; +import { Event, Notification } from './fbs/notification'; +import { parseRtpStreamRecvStats, RtpStreamRecvStats } from './RtpStream'; import { AppData } from './types'; +import * as utils from './utils'; +import * as FbsNotification from './fbs/notification'; +import * as FbsRequest from './fbs/request'; +import * as FbsTransport from './fbs/transport'; +import * as FbsProducer from './fbs/producer'; +import * as FbsProducerTraceInfo from './fbs/producer/trace-info'; +import * as FbsRtpParameters from './fbs/rtp-parameters'; export type ProducerOptions = { @@ -107,35 +115,7 @@ export type ProducerVideoOrientation = rotation: number; }; -export type ProducerStat = -{ - // Common to all RtpStreams. - type: string; - timestamp: number; - ssrc: number; - rtxSsrc?: number; - rid?: string; - kind: string; - mimeType: string; - packetsLost: number; - fractionLost: number; - packetsDiscarded: number; - packetsRetransmitted: number; - packetsRepaired: number; - nackCount: number; - nackPacketCount: number; - pliCount: number; - firCount: number; - score: number; - packetCount: number; - byteCount: number; - bitrate: number; - roundTripTime?: number; - rtxPacketsDiscarded?: number; - // RtpStreamRecv specific. - jitter: number; - bitrateByLayer?: any; -}; +export type ProducerStat = RtpStreamRecvStats; /** * Producer type. @@ -162,6 +142,17 @@ export type ProducerObserverEvents = trace: [ProducerTraceEventData]; }; +type ProducerDump = { + id: string; + kind: string; + type:ProducerType; + rtpParameters:RtpParameters; + rtpMapping:any; + rtpStreams:any; + traceEventTypes:string[]; + paused:boolean; +}; + type ProducerInternal = TransportInternal & { producerId: string; @@ -189,9 +180,6 @@ export class Producer // Channel instance. readonly #channel: Channel; - // PayloadChannel instance. - readonly #payloadChannel: PayloadChannel; - // Closed flag. #closed = false; @@ -215,7 +203,6 @@ export class Producer internal, data, channel, - payloadChannel, appData, paused }: @@ -223,7 +210,6 @@ export class Producer internal: ProducerInternal; data: ProducerData; channel: Channel; - payloadChannel: PayloadChannel; appData?: ProducerAppData; paused: boolean; } @@ -236,7 +222,6 @@ export class Producer this.#internal = internal; this.#data = data; this.#channel = channel; - this.#payloadChannel = payloadChannel; this.#appData = appData || {} as ProducerAppData; this.#paused = paused; @@ -358,12 +343,18 @@ export class Producer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.producerId); - this.#payloadChannel.removeAllListeners(this.#internal.producerId); - const reqData = { producerId: this.#internal.producerId }; + /* Build Request. */ + const requestOffset = new FbsTransport.CloseProducerRequestT( + this.#internal.producerId + ).pack(this.#channel.bufferBuilder); - this.#channel.request('transport.closeProducer', this.#internal.transportId, reqData) - .catch(() => {}); + this.#channel.request( + FbsRequest.Method.TRANSPORT_CLOSE_PRODUCER, + FbsRequest.Body.FBS_Transport_CloseProducerRequest, + requestOffset, + this.#internal.transportId + ).catch(() => {}); this.emit('@close'); @@ -389,7 +380,6 @@ export class Producer // Remove notification subscriptions. this.#channel.removeAllListeners(this.#internal.producerId); - this.#payloadChannel.removeAllListeners(this.#internal.producerId); this.safeEmit('transportclose'); @@ -400,11 +390,23 @@ export class Producer /** * Dump Producer. */ - async dump(): Promise + async dump(): Promise { logger.debug('dump()'); - return this.#channel.request('producer.dump', this.#internal.producerId); + const response = await this.#channel.request( + FbsRequest.Method.PRODUCER_DUMP, + undefined, + undefined, + this.#internal.producerId + ); + + /* Decode Response. */ + const dumpResponse = new FbsProducer.DumpResponse(); + + response.body(dumpResponse); + + return parseProducerDump(dumpResponse); } /** @@ -414,7 +416,19 @@ export class Producer { logger.debug('getStats()'); - return this.#channel.request('producer.getStats', this.#internal.producerId); + const response = await this.#channel.request( + FbsRequest.Method.PRODUCER_GET_STATS, + undefined, + undefined, + this.#internal.producerId + ); + + /* Decode Response. */ + const data = new FbsProducer.GetStatsResponse(); + + response.body(data); + + return parseProducerStats(data); } /** @@ -426,7 +440,12 @@ export class Producer const wasPaused = this.#paused; - await this.#channel.request('producer.pause', this.#internal.producerId); + await this.#channel.request( + FbsRequest.Method.PRODUCER_PAUSE, + undefined, + undefined, + this.#internal.producerId + ); this.#paused = true; @@ -446,7 +465,12 @@ export class Producer const wasPaused = this.#paused; - await this.#channel.request('producer.resume', this.#internal.producerId); + await this.#channel.request( + FbsRequest.Method.PRODUCER_RESUME, + undefined, + undefined, + this.#internal.producerId + ); this.#paused = false; @@ -464,10 +488,26 @@ export class Producer { logger.debug('enableTraceEvent()'); - const reqData = { types }; + if (!Array.isArray(types)) + { + throw new TypeError('types must be an array'); + } + if (types.find((type) => typeof type !== 'string')) + { + throw new TypeError('every type must be a string'); + } + + /* Build Request. */ + const requestOffset = new FbsProducer.EnableTraceEventRequestT( + types + ).pack(this.#channel.bufferBuilder); await this.#channel.request( - 'producer.enableTraceEvent', this.#internal.producerId, reqData); + FbsRequest.Method.PRODUCER_ENABLE_TRACE_EVENT, + FbsRequest.Body.FBS_Producer_EnableTraceEventRequest, + requestOffset, + this.#internal.producerId + ); } /** @@ -480,19 +520,36 @@ export class Producer throw new TypeError('rtpPacket must be a Buffer'); } - this.#payloadChannel.notify( - 'producer.send', this.#internal.producerId, undefined, rtpPacket); + const builder = this.#channel.bufferBuilder; + const dataOffset = FbsProducer.SendNotification.createDataVector(builder, rtpPacket); + const notificationOffset = FbsProducer.SendNotification.createSendNotification( + builder, + dataOffset + ); + + this.#channel.notify( + FbsNotification.Event.PRODUCER_SEND, + FbsNotification.Body.FBS_Producer_SendNotification, + notificationOffset, + this.#internal.producerId + ); } private handleWorkerNotifications(): void { - this.#channel.on(this.#internal.producerId, (event: string, data?: any) => + this.#channel.on(this.#internal.producerId, (event: Event, data?: Notification) => { switch (event) { - case 'score': + case Event.PRODUCER_SCORE: { - const score = data as ProducerScore[]; + const notification = new FbsProducer.ScoreNotification(); + + data!.body(notification); + + const score: ProducerScore[] = utils.parseVector( + notification, 'scores', parseProducerScore + ); this.#score = score; @@ -504,9 +561,13 @@ export class Producer break; } - case 'videoorientationchange': + case Event.PRODUCER_VIDEO_ORIENTATION_CHANGE: { - const videoOrientation = data as ProducerVideoOrientation; + const notification = new FbsProducer.VideoOrientationChangeNotification(); + + data!.body(notification); + + const videoOrientation: ProducerVideoOrientation = notification.unpack(); this.safeEmit('videoorientationchange', videoOrientation); @@ -516,9 +577,13 @@ export class Producer break; } - case 'trace': + case Event.PRODUCER_TRACE: { - const trace = data as ProducerTraceEventData; + const notification = new FbsProducer.TraceNotification(); + + data!.body(notification); + + const trace: ProducerTraceEventData = parseTraceEventData(notification); this.safeEmit('trace', trace); @@ -536,3 +601,83 @@ export class Producer }); } } + +export function parseProducerDump( + data: FbsProducer.DumpResponse +): ProducerDump +{ + return { + id : data.id()!, + kind : data.kind() === FbsRtpParameters.MediaKind.AUDIO ? 'audio' : 'video', + type : data.type()! as ProducerType, + rtpParameters : parseRtpParameters(data.rtpParameters()!), + // NOTE: optional values are represented with null instead of undefined. + // TODO: Make flatbuffers TS return undefined instead of null. + rtpMapping : data.rtpMapping() ? data.rtpMapping()!.unpack() : undefined, + // NOTE: optional values are represented with null instead of undefined. + // TODO: Make flatbuffers TS return undefined instead of null. + rtpStreams : data.rtpStreamsLength() > 0 ? + utils.parseVector(data, 'rtpStreams', (rtpStream: any) => rtpStream.unpack()) : + undefined, + traceEventTypes : utils.parseVector(data, 'traceEventTypes'), + paused : data.paused() + }; +} + +function parseProducerStats(binary: FbsProducer.GetStatsResponse): ProducerStat[] +{ + return utils.parseVector(binary, 'stats', parseRtpStreamRecvStats); +} + +function parseProducerScore( + binary: FbsProducer.Score +): ProducerScore +{ + return { + ssrc : binary.ssrc(), + rid : binary.rid() ?? undefined, + score : binary.score() + }; +} + +function parseTraceEventData( + trace: FbsProducer.TraceNotification +): ProducerTraceEventData +{ + let info: any; + + if (trace.infoType() !== FbsProducer.TraceInfo.NONE) + { + const accessor = trace.info.bind(trace); + + info = FbsProducerTraceInfo.unionToTraceInfo(trace.infoType(), accessor); + + trace.info(info); + } + + return { + type : fbstraceType2String(trace.type()), + timestamp : Number(trace.timestamp()), + direction : trace.direction() === FbsProducer.TraceDirection.DIRECTION_IN ? 'in' : 'out', + info : info ? info.unpack() : undefined + }; +} + +function fbstraceType2String(traceType: FbsProducer.TraceType): ProducerTraceEventType +{ + switch (traceType) + { + case FbsProducer.TraceType.KEYFRAME: + return 'keyframe'; + case FbsProducer.TraceType.FIR: + return 'fir'; + case FbsProducer.TraceType.NACK: + return 'nack'; + case FbsProducer.TraceType.PLI: + return 'pli'; + case FbsProducer.TraceType.RTP: + return 'rtp'; + default: + throw new TypeError(`invalid TraceType: ${traceType}`); + } +} diff --git a/node/src/Router.ts b/node/src/Router.ts index 21466d4c23..f41076338c 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -4,12 +4,11 @@ import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import * as ortc from './ortc'; import { InvalidStateError } from './errors'; import { Channel } from './Channel'; -import { PayloadChannel } from './PayloadChannel'; import { Transport, TransportListenIp } from './Transport'; -import { WebRtcTransport, WebRtcTransportOptions } from './WebRtcTransport'; -import { PlainTransport, PlainTransportOptions } from './PlainTransport'; -import { PipeTransport, PipeTransportOptions } from './PipeTransport'; -import { DirectTransport, DirectTransportOptions } from './DirectTransport'; +import { WebRtcTransport, WebRtcTransportOptions, parseWebRtcTransportDumpResponse } from './WebRtcTransport'; +import { PlainTransport, PlainTransportOptions, parsePlainTransportDumpResponse } from './PlainTransport'; +import { PipeTransport, PipeTransportOptions, parsePipeTransportDumpResponse } from './PipeTransport'; +import { DirectTransport, DirectTransportOptions, parseDirectTransportDumpResponse } from './DirectTransport'; import { Producer } from './Producer'; import { Consumer } from './Consumer'; import { DataProducer } from './DataProducer'; @@ -20,6 +19,17 @@ import { AudioLevelObserver, AudioLevelObserverOptions } from './AudioLevelObser import { RtpCapabilities, RtpCodecCapability } from './RtpParameters'; import { NumSctpStreams } from './SctpParameters'; import { AppData } from './types'; +import * as FbsActiveSpeakerObserver from './fbs/active-speaker-observer'; +import * as FbsAudioLevelObserver from './fbs/audio-level-observer'; +import * as FbsRequest from './fbs/request'; +import * as FbsWorker from './fbs/worker'; +import * as FbsRouter from './fbs/router'; +import * as FbsPlainTransport from './fbs/plain-transport'; +import * as FbsPipeTransport from './fbs/pipe-transport'; +import * as FbsDirectTransport from './fbs/direct-transport'; +import * as FbsWebRtcTransport from './fbs/web-rtc-transport'; +import * as FbsTransport from './fbs/transport'; +import * as FbsSctpParameters from './fbs/sctp-parameters'; export type RouterOptions = { @@ -143,9 +153,6 @@ export class Router // Channel instance. readonly #channel: Channel; - // PayloadChannel instance. - readonly #payloadChannel: PayloadChannel; - // Closed flag. #closed = false; @@ -180,14 +187,12 @@ export class Router internal, data, channel, - payloadChannel, appData }: { internal: RouterInternal; data: RouterData; channel: Channel; - payloadChannel: PayloadChannel; appData?: RouterAppData; } ) @@ -199,7 +204,6 @@ export class Router this.#internal = internal; this.#data = data; this.#channel = channel; - this.#payloadChannel = payloadChannel; this.#appData = appData || {} as RouterAppData; } @@ -274,9 +278,13 @@ export class Router this.#closed = true; - const reqData = { routerId: this.#internal.routerId }; + const requestOffset = new FbsWorker.CloseRouterRequestT( + this.#internal.routerId).pack(this.#channel.bufferBuilder); - this.#channel.request('worker.closeRouter', undefined, reqData) + this.#channel.request( + FbsRequest.Method.WORKER_CLOSE_ROUTER, + FbsRequest.Body.FBS_Worker_CloseRouterRequest, + requestOffset) .catch(() => {}); // Close every Transport. @@ -354,7 +362,20 @@ export class Router { logger.debug('dump()'); - return this.#channel.request('router.dump', this.#internal.routerId); + // Send the request and wait for the response. + const response = await this.#channel.request( + FbsRequest.Method.ROUTER_DUMP, + undefined, + undefined, + this.#internal.routerId + ); + + /* Decode Response. */ + const dump = new FbsRouter.DumpResponse(); + + response.body(dump); + + return dump.unpack(); } /** @@ -384,6 +405,13 @@ export class Router { throw new TypeError('missing webRtcServer and listenIps (one of them is mandatory)'); } + else if ( + numSctpStreams && + (typeof numSctpStreams.OS !== 'number' || typeof numSctpStreams.MIS !== 'number') + ) + { + throw new TypeError('if given, numSctpStreams must contain OS and MID'); + } else if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); @@ -391,6 +419,11 @@ export class Router if (listenIps) { + if (listenIps.length === 0) + { + throw new TypeError('empty listenIps array provided'); + } + listenIps = listenIps.map((listenIp) => { if (typeof listenIp === 'string' && listenIp) @@ -411,38 +444,85 @@ export class Router }); } - const reqData = + const transportId = uuidv4(); + + /* Build Request. */ + let webRtcTransportListenServer: + FbsWebRtcTransport.ListenServerT | undefined; + let webRtcTransportListenIndividual: + FbsWebRtcTransport.ListenIndividualT | undefined; + + if (webRtcServer) { - transportId : uuidv4(), - webRtcServerId : webRtcServer ? webRtcServer.id : undefined, - listenIps, - port, - enableUdp, - enableTcp, - preferUdp, - preferTcp, + webRtcTransportListenServer = + new FbsWebRtcTransport.ListenServerT(webRtcServer.id); + } + else + { + const fbsListenIps: FbsTransport.ListenIpT[] = []; + + for (const listenIp of listenIps as any[]) + { + fbsListenIps.push( + new FbsTransport.ListenIpT(listenIp.ip, listenIp.announcedIp)); + } + + webRtcTransportListenIndividual = + new FbsWebRtcTransport.ListenIndividualT(fbsListenIps, port); + } + + const baseTransportOptions = new FbsTransport.OptionsT( + undefined /* direct */, + undefined /* maxMessageSize */, initialAvailableOutgoingBitrate, enableSctp, - numSctpStreams, + new FbsSctpParameters.NumSctpStreamsT(numSctpStreams.OS, numSctpStreams.MIS), maxSctpMessageSize, sctpSendBufferSize, - isDataChannel : true - }; + true /* isDataChannel */ + ); + + const webRtcTransportOptions = new FbsWebRtcTransport.WebRtcTransportOptionsT( + baseTransportOptions, + webRtcServer ? + FbsWebRtcTransport.Listen.ListenServer : + FbsWebRtcTransport.Listen.ListenIndividual, + webRtcServer ? webRtcTransportListenServer : webRtcTransportListenIndividual, + enableUdp, + enableTcp, + preferUdp, + preferTcp + ); - const data = webRtcServer - ? await this.#channel.request('router.createWebRtcTransportWithServer', this.#internal.routerId, reqData) - : await this.#channel.request('router.createWebRtcTransport', this.#internal.routerId, reqData); + const requestOffset = new FbsRouter.CreateWebRtcTransportRequestT( + transportId, webRtcTransportOptions + ).pack(this.#channel.bufferBuilder); + + const response = await this.#channel.request( + webRtcServer + ? FbsRequest.Method.ROUTER_CREATE_WEBRTC_TRANSPORT_WITH_SERVER + : FbsRequest.Method.ROUTER_CREATE_WEBRTC_TRANSPORT, + FbsRequest.Body.FBS_Router_CreateWebRtcTransportRequest, + requestOffset, + this.#internal.routerId + ); + + /* Decode Response. */ + const data = new FbsWebRtcTransport.DumpResponse(); + + response.body(data); + + const webRtcTransportData = parseWebRtcTransportDumpResponse(data); const transport = new WebRtcTransport( { internal : { ...this.#internal, - transportId : reqData.transportId + transportId : transportId }, - data, + data : webRtcTransportData, channel : this.#channel, - payloadChannel : this.#payloadChannel, appData, getRouterRtpCapabilities : (): RtpCapabilities => this.#data.rtpCapabilities, getProducerById : (producerId: string): Producer | undefined => ( @@ -523,35 +603,66 @@ export class Router throw new TypeError('wrong listenIp'); } - const reqData = - { - transportId : uuidv4(), - listenIp, - port, - rtcpMux, - comedia, + const transportId = uuidv4(); + + /* Build Request. */ + const baseTransportOptions = new FbsTransport.OptionsT( + undefined /* direct */, + undefined /* maxMessageSize */, + undefined /* initialAvailableOutgoingBitrate */, enableSctp, - numSctpStreams, + new FbsSctpParameters.NumSctpStreamsT(numSctpStreams.OS, numSctpStreams.MIS), maxSctpMessageSize, sctpSendBufferSize, - isDataChannel : false, + false /* isDataChannel */ + ); + + const plainTransportOptions = new FbsPlainTransport.PlainTransportOptionsT( + baseTransportOptions, + new FbsTransport.ListenIpT(listenIp.ip, listenIp.announcedIp), + port, + rtcpMux, + comedia, enableSrtp, srtpCryptoSuite - }; + ); + + let requestOffset; + + try + { + requestOffset = new FbsRouter.CreatePlainTransportRequestT( + transportId, plainTransportOptions + ).pack(this.#channel.bufferBuilder); + } + catch (error) + { + throw new TypeError((error as Error).message); + } + + const response = await this.#channel.request( + FbsRequest.Method.ROUTER_CREATE_PLAIN_TRANSPORT, + FbsRequest.Body.FBS_Router_CreatePlainTransportRequest, + requestOffset, + this.#internal.routerId + ); - const data = - await this.#channel.request('router.createPlainTransport', this.#internal.routerId, reqData); + /* Decode Response. */ + const data = new FbsPlainTransport.DumpResponse(); + + response.body(data); + + const plainTransportData = parsePlainTransportDumpResponse(data); const transport = new PlainTransport( { internal : { ...this.#internal, - transportId : reqData.transportId + transportId : transportId }, - data, + data : plainTransportData, channel : this.#channel, - payloadChannel : this.#payloadChannel, appData, getRouterRtpCapabilities : (): RtpCapabilities => this.#data.rtpCapabilities, getProducerById : (producerId: string): Producer | undefined => ( @@ -625,33 +736,55 @@ export class Router throw new TypeError('wrong listenIp'); } - const reqData = - { - transportId : uuidv4(), - listenIp, - port, + const transportId = uuidv4(); + + /* Build Request. */ + const baseTransportOptions = new FbsTransport.OptionsT( + undefined /* direct */, + undefined /* maxMessageSize */, + undefined /* initialAvailableOutgoingBitrate */, enableSctp, - numSctpStreams, + new FbsSctpParameters.NumSctpStreamsT(numSctpStreams.OS, numSctpStreams.MIS), maxSctpMessageSize, sctpSendBufferSize, - isDataChannel : false, + false /* isDataChannel */ + ); + + const pipeTransportOptions = new FbsPipeTransport.PipeTransportOptionsT( + baseTransportOptions, + new FbsTransport.ListenIpT(listenIp.ip, listenIp.announcedIp), + port, enableRtx, enableSrtp - }; + ); + + const requestOffset = new FbsRouter.CreatePipeTransportRequestT( + transportId, pipeTransportOptions + ).pack(this.#channel.bufferBuilder); + + const response = await this.#channel.request( + FbsRequest.Method.ROUTER_CREATE_PIPE_TRANSPORT, + FbsRequest.Body.FBS_Router_CreatePipeTransportRequest, + requestOffset, + this.#internal.routerId + ); + + /* Decode Response. */ + const data = new FbsPipeTransport.DumpResponse(); + + response.body(data); - const data = - await this.#channel.request('router.createPipeTransport', this.#internal.routerId, reqData); + const plainTransportData = parsePipeTransportDumpResponse(data); const transport = new PipeTransport( { internal : { ...this.#internal, - transportId : reqData.transportId + transportId }, - data, + data : plainTransportData, channel : this.#channel, - payloadChannel : this.#payloadChannel, appData, getRouterRtpCapabilities : (): RtpCapabilities => this.#data.rtpCapabilities, getProducerById : (producerId: string): Producer | undefined => ( @@ -695,26 +828,60 @@ export class Router { logger.debug('createDirectTransport()'); - const reqData = + if (typeof maxMessageSize !== 'number' || maxMessageSize < 0) { - transportId : uuidv4(), - direct : true, - maxMessageSize - }; + throw new TypeError('if given, maxMessageSize must be a positive number'); + } + else if (appData && typeof appData !== 'object') + { + throw new TypeError('if given, appData must be an object'); + } - const data = - await this.#channel.request('router.createDirectTransport', this.#internal.routerId, reqData); + const transportId = uuidv4(); + + /* Build Request. */ + const baseTransportOptions = new FbsTransport.OptionsT( + true /* direct */, + maxMessageSize, + undefined /* initialAvailableOutgoingBitrate */, + undefined /* enableSctp */, + undefined /* numSctpStreams */, + undefined /* maxSctpMessageSize */, + undefined /* sctpSendBufferSize */, + undefined /* isDataChannel */ + ); + + const directTransportOptions = new FbsDirectTransport.DirectTransportOptionsT( + baseTransportOptions + ); + + const requestOffset = new FbsRouter.CreateDirectTransportRequestT( + transportId, directTransportOptions + ).pack(this.#channel.bufferBuilder); + + const response = await this.#channel.request( + FbsRequest.Method.ROUTER_CREATE_DIRECT_TRANSPORT, + FbsRequest.Body.FBS_Router_CreateDirectTransportRequest, + requestOffset, + this.#internal.routerId + ); + + /* Decode Response. */ + const data = new FbsDirectTransport.DumpResponse(); + + response.body(data); + + const directTransportData = parseDirectTransportDumpResponse(data); const transport = new DirectTransport( { internal : { ...this.#internal, - transportId : reqData.transportId + transportId : transportId }, - data, + data : directTransportData, channel : this.#channel, - payloadChannel : this.#payloadChannel, appData, getRouterRtpCapabilities : (): RtpCapabilities => this.#data.rtpCapabilities, getProducerById : (producerId: string): Producer | undefined => ( @@ -1076,34 +1243,50 @@ export class Router { logger.debug('createActiveSpeakerObserver()'); + if (typeof interval !== 'number') + { + throw new TypeError('if given, interval must be an number'); + } if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } - - const reqData = - { - rtpObserverId : uuidv4(), - interval - }; - await this.#channel.request('router.createActiveSpeakerObserver', this.#internal.routerId, reqData); + const rtpObserverId = uuidv4(); + + /* Build Request. */ + const activeRtpObserverOptions = + new FbsActiveSpeakerObserver.ActiveSpeakerObserverOptionsT( + interval + ); + + const requestOffset = + new FbsRouter.CreateActiveSpeakerObserverRequestT( + rtpObserverId, + activeRtpObserverOptions + ).pack(this.#channel.bufferBuilder); + + await this.#channel.request( + FbsRequest.Method.ROUTER_CREATE_ACTIVE_SPEAKER_OBSERVER, + FbsRequest.Body.FBS_Router_CreateActiveSpeakerObserverRequest, + requestOffset, + this.#internal.routerId + ); const activeSpeakerObserver = new ActiveSpeakerObserver( { internal : { ...this.#internal, - rtpObserverId : reqData.rtpObserverId + rtpObserverId : rtpObserverId }, channel : this.#channel, - payloadChannel : this.#payloadChannel, appData, getProducerById : (producerId: string): Producer | undefined => ( this.#producers.get(producerId) ) }); - + this.#rtpObservers.set(activeSpeakerObserver.id, activeSpeakerObserver); activeSpeakerObserver.on('@close', () => { @@ -1130,30 +1313,53 @@ export class Router { logger.debug('createAudioLevelObserver()'); + if (typeof maxEntries !== 'number' || maxEntries <= 0) + { + throw new TypeError('if given, maxEntries must be a positive number'); + } + if (typeof threshold !== 'number' || threshold < -127 || threshold > 0) + { + throw new TypeError('if given, threshole must be a negative number greater than -127'); + } + if (typeof interval !== 'number') + { + throw new TypeError('if given, interval must be an number'); + } if (appData && typeof appData !== 'object') { throw new TypeError('if given, appData must be an object'); } - const reqData = - { - rtpObserverId : uuidv4(), - maxEntries, - threshold, - interval - }; + const rtpObserverId = uuidv4(); + + /* Build Request. */ + const audioLevelObserverOptions = + new FbsAudioLevelObserver.AudioLevelObserverOptionsT( + maxEntries, + threshold, + interval + ); + + const requestOffset = new FbsRouter.CreateAudioLevelObserverRequestT( + rtpObserverId, + audioLevelObserverOptions + ).pack(this.#channel.bufferBuilder); - await this.#channel.request('router.createAudioLevelObserver', this.#internal.routerId, reqData); + await this.#channel.request( + FbsRequest.Method.ROUTER_CREATE_AUDIO_LEVEL_OBSERVER, + FbsRequest.Body.FBS_Router_CreateAudioLevelObserverRequest, + requestOffset, + this.#internal.routerId + ); const audioLevelObserver = new AudioLevelObserver( { internal : { ...this.#internal, - rtpObserverId : reqData.rtpObserverId + rtpObserverId : rtpObserverId }, channel : this.#channel, - payloadChannel : this.#payloadChannel, appData, getProducerById : (producerId: string): Producer | undefined => ( this.#producers.get(producerId) diff --git a/node/src/RtpObserver.ts b/node/src/RtpObserver.ts index 3821d728d4..3ba450f722 100644 --- a/node/src/RtpObserver.ts +++ b/node/src/RtpObserver.ts @@ -1,10 +1,12 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import { Channel } from './Channel'; -import { PayloadChannel } from './PayloadChannel'; import { RouterInternal } from './Router'; import { Producer } from './Producer'; import { AppData } from './types'; +import * as FbsRequest from './fbs/request'; +import * as FbsRouter from './fbs/router'; +import * as FbsRtpObserver from './fbs/rtp-observer'; export type RtpObserverEvents = { @@ -26,7 +28,6 @@ export type RtpObserverConstructorOptions = { internal: RtpObserverObserverInternal; channel: Channel; - payloadChannel: PayloadChannel; appData?: RtpObserverAppData; getProducerById: (producerId: string) => Producer | undefined; }; @@ -57,9 +58,6 @@ export class RtpObserver // Channel instance. protected readonly channel: Channel; - // PayloadChannel instance. - protected readonly payloadChannel: PayloadChannel; - // Closed flag. #closed = false; @@ -83,7 +81,6 @@ export class RtpObserver { internal, channel, - payloadChannel, appData, getProducerById }: RtpObserverConstructorOptions @@ -95,7 +92,6 @@ export class RtpObserver this.internal = internal; this.channel = channel; - this.payloadChannel = payloadChannel; this.#appData = appData || {} as RtpObserverAppData; this.getProducerById = getProducerById; } @@ -164,12 +160,18 @@ export class RtpObserver // Remove notification subscriptions. this.channel.removeAllListeners(this.internal.rtpObserverId); - this.payloadChannel.removeAllListeners(this.internal.rtpObserverId); - const reqData = { rtpObserverId: this.internal.rtpObserverId }; + /* Build Request. */ + const requestOffset = new FbsRouter.CloseRtpObserverRequestT( + this.internal.rtpObserverId + ).pack(this.channel.bufferBuilder); - this.channel.request('router.closeRtpObserver', this.internal.routerId, reqData) - .catch(() => {}); + this.channel.request( + FbsRequest.Method.ROUTER_CLOSE_RTP_OBSERVER, + FbsRequest.Body.FBS_Router_CloseRtpObserverRequest, + requestOffset, + this.internal.routerId + ).catch(() => {}); this.emit('@close'); @@ -195,7 +197,6 @@ export class RtpObserver // Remove notification subscriptions. this.channel.removeAllListeners(this.internal.rtpObserverId); - this.payloadChannel.removeAllListeners(this.internal.rtpObserverId); this.safeEmit('routerclose'); @@ -212,7 +213,12 @@ export class RtpObserver const wasPaused = this.#paused; - await this.channel.request('rtpObserver.pause', this.internal.rtpObserverId); + await this.channel.request( + FbsRequest.Method.RTP_OBSERVER_PAUSE, + undefined, + undefined, + this.internal.rtpObserverId + ); this.#paused = true; @@ -232,7 +238,12 @@ export class RtpObserver const wasPaused = this.#paused; - await this.channel.request('rtpObserver.resume', this.internal.rtpObserverId); + await this.channel.request( + FbsRequest.Method.RTP_OBSERVER_RESUME, + undefined, + undefined, + this.internal.rtpObserverId + ); this.#paused = false; @@ -257,9 +268,16 @@ export class RtpObserver throw Error(`Producer with id "${producerId}" not found`); } - const reqData = { producerId }; + const requestOffset = new FbsRtpObserver.AddProducerRequestT( + producerId + ).pack(this.channel.bufferBuilder); - await this.channel.request('rtpObserver.addProducer', this.internal.rtpObserverId, reqData); + await this.channel.request( + FbsRequest.Method.RTP_OBSERVER_ADD_PRODUCER, + FbsRequest.Body.FBS_RtpObserver_AddProducerRequest, + requestOffset, + this.internal.rtpObserverId + ); // Emit observer event. this.#observer.safeEmit('addproducer', producer); @@ -279,9 +297,16 @@ export class RtpObserver throw Error(`Producer with id "${producerId}" not found`); } - const reqData = { producerId }; + const requestOffset = new FbsRtpObserver.RemoveProducerRequestT( + producerId + ).pack(this.channel.bufferBuilder); - await this.channel.request('rtpObserver.removeProducer', this.internal.rtpObserverId, reqData); + await this.channel.request( + FbsRequest.Method.RTP_OBSERVER_REMOVE_PRODUCER, + FbsRequest.Body.FBS_RtpObserver_RemoveProducerRequest, + requestOffset, + this.internal.rtpObserverId + ); // Emit observer event. this.#observer.safeEmit('removeproducer', producer); diff --git a/node/src/RtpParameters.ts b/node/src/RtpParameters.ts index c26cc86b3f..f7b7b94554 100644 --- a/node/src/RtpParameters.ts +++ b/node/src/RtpParameters.ts @@ -1,3 +1,22 @@ +import * as flatbuffers from 'flatbuffers'; +import { + Boolean as FbsBoolean, + Double as FbsDouble, + Integer as FbsInteger, + IntegerArray as FbsIntegerArray, + String as FbsString, + Parameter as FbsParameter, + RtcpFeedback as FbsRtcpFeedback, + RtcpParameters as FbsRtcpParameters, + RtpCodecParameters as FbsRtpCodecParameters, + RtpEncodingParameters as FbsRtpEncodingParameters, + RtpHeaderExtensionParameters as FbsRtpHeaderExtensionParameters, + RtpParameters as FbsRtpParameters, + Rtx as FbsRtx, + Value as FbsValue +} from './fbs/rtp-parameters'; +import * as utils from './utils'; + /** * The RTP capabilities define what mediasoup or an endpoint can receive at * media level. @@ -345,9 +364,427 @@ export type RtcpParameters = * as specified in RFC 3550 (if false). Default true. */ reducedSize?: boolean; - - /** - * Whether RTCP-mux is used. Default true. - */ - mux?: boolean; }; + +export function serializeRtpParameters( + builder: flatbuffers.Builder, rtpParameters: RtpParameters +): number +{ + const codecs: number[] = []; + const headerExtensions: number[] = []; + + for (const codec of rtpParameters.codecs) + { + const mimeTypeOffset = builder.createString(codec.mimeType); + const parameters = serializeParameters(builder, codec.parameters); + const parametersOffset = + FbsRtpCodecParameters.createParametersVector(builder, parameters); + + const rtcpFeedback: number[] = []; + + for (const rtcp of codec.rtcpFeedback?? []) + { + const typeOffset = builder.createString(rtcp.type); + const rtcpParametersOffset = builder.createString(rtcp.parameter); + + rtcpFeedback.push( + FbsRtcpFeedback.createRtcpFeedback(builder, typeOffset, rtcpParametersOffset)); + } + const rtcpFeedbackOffset = + FbsRtpCodecParameters.createRtcpFeedbackVector(builder, rtcpFeedback); + + codecs.push( + FbsRtpCodecParameters.createRtpCodecParameters( + builder, + mimeTypeOffset, + codec.payloadType, + codec.clockRate, + Number(codec.channels), + parametersOffset, + rtcpFeedbackOffset + )); + } + const codecsOffset = FbsRtpParameters.createCodecsVector(builder, codecs); + + // RtpHeaderExtensionParameters. + for (const headerExtension of rtpParameters.headerExtensions ?? []) + { + const uriOffset = builder.createString(headerExtension.uri); + const parameters = serializeParameters(builder, headerExtension.parameters); + const parametersOffset = + FbsRtpCodecParameters.createParametersVector(builder, parameters); + + headerExtensions.push( + FbsRtpHeaderExtensionParameters.createRtpHeaderExtensionParameters( + builder, + uriOffset, + headerExtension.id, + Boolean(headerExtension.encrypt), + parametersOffset)); + } + const headerExtensionsOffset = + FbsRtpParameters.createHeaderExtensionsVector(builder, headerExtensions); + + // RtpEncodingParameters. + let encodingsOffset: number | undefined; + + if (rtpParameters.encodings) + { + encodingsOffset = serializeRtpEncodingParameters(builder, rtpParameters.encodings); + } + + // RtcpParameters. + let rtcpOffset: number | undefined; + + if (rtpParameters.rtcp) + { + const { cname, reducedSize } = rtpParameters.rtcp; + const cnameOffset = builder.createString(cname); + + rtcpOffset = FbsRtcpParameters.createRtcpParameters( + builder, cnameOffset, Boolean(reducedSize) + ); + } + + const midOffset = builder.createString(rtpParameters.mid); + + FbsRtpParameters.startRtpParameters(builder); + FbsRtpParameters.addMid(builder, midOffset); + FbsRtpParameters.addCodecs(builder, codecsOffset); + + if (headerExtensions.length > 0) + { + FbsRtpParameters.addHeaderExtensions(builder, headerExtensionsOffset); + } + + if (encodingsOffset) + { + FbsRtpParameters.addEncodings(builder, encodingsOffset); + } + + if (rtcpOffset) + { + FbsRtpParameters.addRtcp(builder, rtcpOffset); + } + + return FbsRtpParameters.endRtpParameters(builder); +} + +export function serializeRtpEncodingParameters( + builder: flatbuffers.Builder, rtpEncodingParameters: RtpEncodingParameters[] +): number +{ + const encodings: number[] = []; + + for (const encoding of rtpEncodingParameters ?? []) + { + // Prepare Rid. + const ridOffset = builder.createString(encoding.rid); + + // Prepare Rtx. + let rtxOffset: number | undefined; + + if (encoding.rtx) + { + rtxOffset = FbsRtx.createRtx(builder, encoding.rtx.ssrc); + } + + // Prepare scalability mode. + let scalabilityModeOffset: number | undefined; + + if (encoding.scalabilityMode) + { + scalabilityModeOffset = builder.createString(encoding.scalabilityMode); + } + + // Start serialization. + FbsRtpEncodingParameters.startRtpEncodingParameters(builder); + + // Add SSRC. + if (encoding.ssrc) + { + FbsRtpEncodingParameters.addSsrc(builder, encoding.ssrc); + } + + // Add Rid. + FbsRtpEncodingParameters.addRid(builder, ridOffset); + + // Add payload type. + if (encoding.codecPayloadType) + { + FbsRtpEncodingParameters.addCodecPayloadType(builder, encoding.codecPayloadType); + } + + // Add RTX. + if (rtxOffset) + { + FbsRtpEncodingParameters.addRtx(builder, rtxOffset); + } + + // Add DTX. + if (encoding.dtx !== undefined) + { + FbsRtpEncodingParameters.addDtx(builder, encoding.dtx); + } + + // Add scalability ode. + if (scalabilityModeOffset) + { + FbsRtpEncodingParameters.addScalabilityMode(builder, scalabilityModeOffset); + } + + // Add max bitrate. + if (encoding.maxBitrate !== undefined) + { + FbsRtpEncodingParameters.addMaxBitrate(builder, encoding.maxBitrate); + } + + // End serialization. + encodings.push(FbsRtpEncodingParameters.endRtpEncodingParameters(builder)); + } + + return FbsRtpParameters.createEncodingsVector(builder, encodings); +} + +export function serializeParameters( + builder: flatbuffers.Builder, parameters: any +):number[] +{ + const fbsParameters: number[] = []; + + for (const key of Object.keys(parameters)) + { + const value = parameters[key]; + const keyOffset = builder.createString(key); + let parameterOffset: number; + + if (typeof value === 'boolean') + { + parameterOffset = FbsParameter.createParameter( + builder, keyOffset, FbsValue.Boolean, value === true ? 1:0 + ); + } + + else if (typeof value === 'number') + { + // Integer. + if (value % 1 === 0) + { + const valueOffset = FbsInteger.createInteger(builder, value); + + parameterOffset = FbsParameter.createParameter( + builder, keyOffset, FbsValue.Integer, valueOffset + ); + } + // Float. + else + { + const valueOffset = FbsDouble.createDouble(builder, value); + + parameterOffset = FbsParameter.createParameter( + builder, keyOffset, FbsValue.Double, valueOffset + ); + } + } + + else if (typeof value === 'string') + { + const valueOffset = FbsString.createString(builder, builder.createString(value)); + + parameterOffset = FbsParameter.createParameter( + builder, keyOffset, FbsValue.String, valueOffset + ); + } + + else if (Array.isArray(value)) + { + const valueOffset = FbsIntegerArray.createValueVector(builder, value); + + parameterOffset = FbsParameter.createParameter( + builder, keyOffset, FbsValue.IntegerArray, valueOffset + ); + } + + else + { + throw new Error(`invalid parameter type [key:'${key}', value:${value}]`); + } + + fbsParameters.push(parameterOffset); + } + + return fbsParameters; +} + +export function parseRtcpFeedback(data: FbsRtcpFeedback): RtcpFeedback +{ + return { + type : data.type()!, + parameter : data.parameter() ?? undefined + }; +} + +export function parseParameters(data: any): any +{ + const parameters: any = {}; + + for (let i=0; i 0) + { + rtcpFeedback = utils.parseVector(data, 'rtcpFeedback', parseRtcpFeedback); + } + + return { + mimeType : data.mimeType()!, + payloadType : data.payloadType(), + clockRate : data.clockRate(), + channels : data.channels() ?? undefined, + parameters, + rtcpFeedback + }; +} + +export function parseRtpHeaderExtensionParameters( + data: FbsRtpHeaderExtensionParameters): RtpHeaderExtensionParameters +{ + return { + uri : data.uri()!, + id : data.id(), + encrypt : data.encrypt(), + parameters : parseParameters(data) + }; +} + +export function parseRtpEncodingParameters( + data: FbsRtpEncodingParameters): RtpEncodingParameters +{ + return { + ssrc : data.ssrc() ?? undefined, + rid : data.rid() ?? undefined, + codecPayloadType : data.codecPayloadType() !== null ? + data.codecPayloadType()! : + undefined, + rtx : data.rtx() ? + { ssrc: data.rtx()!.ssrc()! } : + undefined, + dtx : data.dtx(), + scalabilityMode : data.scalabilityMode() ?? undefined, + maxBitrate : data.maxBitrate() !== null ? data.maxBitrate()! : undefined + }; +} + +export function parseRtpParameters(data: FbsRtpParameters): RtpParameters +{ + const codecs = utils.parseVector(data, 'codecs', parseRtpCodecParameters); + + let headerExtensions: RtpHeaderExtensionParameters[] = []; + + if (data.headerExtensionsLength() > 0) + { + headerExtensions = utils.parseVector( + data, + 'headerExtensions', + parseRtpHeaderExtensionParameters); + } + + let encodings: RtpEncodingParameters[] = []; + + if (data.encodingsLength() > 0) + { + encodings = utils.parseVector( + data, + 'encodings', + parseRtpEncodingParameters); + } + + let rtcp: RtcpParameters | undefined; + + if (data.rtcp()) + { + const fbsRtcp = data.rtcp()!; + + rtcp = { + cname : fbsRtcp.cname() ?? undefined, + reducedSize : fbsRtcp.reducedSize() + }; + } + + return { + mid : data.mid() ?? undefined, + codecs, + headerExtensions, + encodings, + rtcp + }; +} diff --git a/node/src/RtpStream.ts b/node/src/RtpStream.ts new file mode 100644 index 0000000000..aa986cd46c --- /dev/null +++ b/node/src/RtpStream.ts @@ -0,0 +1,138 @@ +import * as FbsRtpStream from './fbs/rtp-stream'; +import * as FbsRtpParameters from './fbs/rtp-parameters'; + +export type RtpStreamRecvStats = BaseRtpStreamStats & { + type: string; + jitter: number; + packetCount: number; + byteCount: number; + bitrate: number; + bitrateByLayer?: any; +}; + +export type RtpStreamSendStats = BaseRtpStreamStats & { + type: string; + packetCount: number; + byteCount: number; + bitrate: number; +}; + +type BaseRtpStreamStats = { + timestamp: number; + ssrc: number; + rtxSsrc?: number; + rid?: string; + kind: string; + mimeType: string; + packetsLost: number; + fractionLost: number; + packetsDiscarded: number; + packetsRetransmitted: number; + packetsRepaired: number; + nackCount: number; + nackPacketCount: number; + pliCount: number; + firCount: number; + score: number; + roundTripTime?: number; + rtxPacketsDiscarded?: number; +}; + +export function parseRtpStreamStats(binary: FbsRtpStream.Stats) + : RtpStreamRecvStats | RtpStreamSendStats +{ + if (binary.dataType() === FbsRtpStream.StatsData.RecvStats) + { + return parseRtpStreamRecvStats(binary); + } + else + { + return parseSendStreamStats(binary); + } +} + +export function parseRtpStreamRecvStats(binary: FbsRtpStream.Stats): RtpStreamRecvStats +{ + const recvStats = new FbsRtpStream.RecvStats(); + const baseStats = new FbsRtpStream.BaseStats(); + + binary.data(recvStats); + recvStats.base()!.data(baseStats); + + const base = parseBaseStreamStats(baseStats); + + return { + ...base, + type : 'inbound-rtp', + jitter : recvStats.jitter(), + byteCount : Number(recvStats.byteCount()), + packetCount : Number(recvStats.packetCount()), + bitrate : Number(recvStats.bitrate()), + bitrateByLayer : parseBitrateByLayer(recvStats) + }; +} + +export function parseSendStreamStats(binary: FbsRtpStream.Stats): RtpStreamSendStats +{ + const sendStats = new FbsRtpStream.SendStats(); + const baseStats = new FbsRtpStream.BaseStats(); + + binary.data(sendStats); + sendStats.base()!.data(baseStats); + + const base = parseBaseStreamStats(baseStats); + + return { + ...base, + type : 'outbound-rtp', + byteCount : Number(sendStats.byteCount()), + packetCount : Number(sendStats.packetCount()), + bitrate : Number(sendStats.bitrate()) + }; +} + +function parseBaseStreamStats(binary: FbsRtpStream.BaseStats): BaseRtpStreamStats +{ + return { + timestamp : Number(binary.timestamp()), + ssrc : binary.ssrc(), + rtxSsrc : binary.rtxSsrc() ?? undefined, + rid : binary.rid() ?? undefined, + kind : binary.kind() === FbsRtpParameters.MediaKind.AUDIO ? + 'audio' : + 'video', + mimeType : binary.mimeType()!, + packetsLost : Number(binary.packetsLost()), + fractionLost : Number(binary.fractionLost()), + packetsDiscarded : Number(binary.packetsDiscarded()), + packetsRetransmitted : Number(binary.packetsRetransmitted()), + packetsRepaired : Number(binary.packetsRepaired()), + nackCount : Number(binary.nackCount()), + nackPacketCount : Number(binary.nackPacketCount()), + pliCount : Number(binary.pliCount()), + firCount : Number(binary.firCount()), + score : binary.score(), + roundTripTime : binary.roundTripTime(), + rtxPacketsDiscarded : binary.rtxPacketsDiscarded() ? + Number(binary.rtxPacketsDiscarded()) : + undefined + }; +} + +function parseBitrateByLayer(binary: FbsRtpStream.RecvStats): any +{ + if (binary.bitrateByLayerLength() === 0) + { + return {}; + } + + const bitRateByLayer: {[key: string]: number} = {}; + + for (let i=0; i < binary.bitrateByLayerLength(); ++i) + { + const layer: string = binary.bitrateByLayer(i)!.layer()!; + const bitrate = binary.bitrateByLayer(i)!.bitrate(); + + bitRateByLayer[layer] = Number(bitrate); + } +} diff --git a/node/src/SctpParameters.ts b/node/src/SctpParameters.ts index 82079d4516..54a878fb6a 100644 --- a/node/src/SctpParameters.ts +++ b/node/src/SctpParameters.ts @@ -1,3 +1,6 @@ +import * as flatbuffers from 'flatbuffers'; +import * as FbsSctpParameters from './fbs/sctp-parameters'; + export type SctpCapabilities = { numStreams: NumSctpStreams; @@ -93,3 +96,63 @@ export type SctpStreamParameters = */ maxRetransmits?: number; }; + +export type SctpParametersDump = +{ + port : number; + OS : number; + MIS : number; + maxMessageSize : number; + sendBufferSize : number; + sctpBufferedAmount : number; + isDataChannel : boolean; +}; + +export function parseSctpParametersDump( + binary: FbsSctpParameters.SctpParameters +): SctpParametersDump +{ + return { + port : binary.port(), + OS : binary.os(), + MIS : binary.mis(), + maxMessageSize : binary.maxMessageSize(), + sendBufferSize : binary.sendBufferSize(), + sctpBufferedAmount : binary.sctpBufferedAmount(), + isDataChannel : binary.isDataChannel() + }; +} + +export function serializeSctpStreamParameters( + builder: flatbuffers.Builder, + parameters: SctpStreamParameters +): number +{ + return FbsSctpParameters.SctpStreamParameters.createSctpStreamParameters( + builder, + parameters.streamId, + parameters.ordered!, + typeof parameters.maxPacketLifeTime === 'number' ? + parameters.maxPacketLifeTime : + null, + typeof parameters.maxRetransmits === 'number' ? + parameters.maxRetransmits : + null + ); +} + +export function parseSctpStreamParameters( + parameters: FbsSctpParameters.SctpStreamParameters +): SctpStreamParameters +{ + return { + streamId : parameters.streamId(), + ordered : parameters.ordered()!, + maxPacketLifeTime : parameters.maxPacketLifeTime() !== null ? + parameters.maxPacketLifeTime()! : + undefined, + maxRetransmits : parameters.maxRetransmits() !== null ? + parameters.maxRetransmits()! : + undefined + }; +} diff --git a/node/src/SrtpParameters.ts b/node/src/SrtpParameters.ts index 1cbddce46c..412c4c6ec9 100644 --- a/node/src/SrtpParameters.ts +++ b/node/src/SrtpParameters.ts @@ -1,3 +1,6 @@ +import * as flatbuffers from 'flatbuffers'; +import * as FbsTransport from './fbs/transport'; + /** * SRTP parameters. */ @@ -22,3 +25,23 @@ export type SrtpCryptoSuite = | 'AEAD_AES_128_GCM' | 'AES_CM_128_HMAC_SHA1_80' | 'AES_CM_128_HMAC_SHA1_32'; + +export function parseSrtpParameters(binary: FbsTransport.SrtpParameters): SrtpParameters +{ + return { + cryptoSuite : binary.cryptoSuite()! as SrtpCryptoSuite, + keyBase64 : binary.keyBase64()! + }; +} + +export function serializeSrtpParameters( + builder:flatbuffers.Builder, srtpParameters:SrtpParameters +): number +{ + const cryptoSuiteOffset = builder.createString(srtpParameters.cryptoSuite); + const keyBase64Offset = builder.createString(srtpParameters.keyBase64); + + return FbsTransport.SrtpParameters.createSrtpParameters( + builder, cryptoSuiteOffset, keyBase64Offset + ); +} diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 5d31e794ac..c1cec39978 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -1,30 +1,51 @@ import { v4 as uuidv4 } from 'uuid'; +import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import * as utils from './utils'; import * as ortc from './ortc'; import { Channel } from './Channel'; -import { PayloadChannel } from './PayloadChannel'; import { RouterInternal } from './Router'; import { WebRtcTransportData } from './WebRtcTransport'; import { PlainTransportData } from './PlainTransport'; import { PipeTransportData } from './PipeTransport'; import { DirectTransportData } from './DirectTransport'; import { Producer, ProducerOptions } from './Producer'; -import { Consumer, ConsumerOptions, ConsumerType } from './Consumer'; +import { Consumer, ConsumerLayers, ConsumerOptions, ConsumerType } from './Consumer'; import { DataProducer, DataProducerOptions, - DataProducerType + DataProducerType, + parseDataProducerDump } from './DataProducer'; import { DataConsumer, DataConsumerOptions, - DataConsumerType + DataConsumerType, + parseDataConsumerDump } from './DataConsumer'; -import { RtpCapabilities } from './RtpParameters'; -import { SctpStreamParameters } from './SctpParameters'; +import { + MediaKind, + RtpCapabilities, + RtpParameters, + serializeRtpEncodingParameters, + serializeRtpParameters +} from './RtpParameters'; +import { + parseSctpParametersDump, + serializeSctpStreamParameters, + SctpParameters, + SctpStreamParameters +} from './SctpParameters'; import { AppData } from './types'; +import * as FbsRequest from './fbs/request'; +import { MediaKind as FbsMediaKind } from './fbs/rtp-parameters/media-kind'; +import * as FbsConsumer from './fbs/consumer'; +import * as FbsDataConsumer from './fbs/data-consumer'; +import * as FbsDataProducer from './fbs/data-producer'; +import * as FbsTransport from './fbs/transport'; +import * as FbsRouter from './fbs/router'; +import { SctpState as FbsSctpState } from './fbs/sctp-association/sctp-state'; export type TransportListenIp = { @@ -116,7 +137,6 @@ export type TransportConstructorOptions = internal: TransportInternal; data: TransportData; channel: Channel; - payloadChannel: PayloadChannel; appData?: TransportAppData; getRouterRtpCapabilities: () => RtpCapabilities; getProducerById: (producerId: string) => Producer | undefined; @@ -128,12 +148,63 @@ export type TransportInternal = RouterInternal & transportId: string; }; +export type BaseTransportDump = { + id : string; + direct : boolean; + producerIds : string[]; + consumerIds : string[]; + mapSsrcConsumerId : { key: number; value: string }[]; + mapRtxSsrcConsumerId : { key: number; value: string }[]; + recvRtpHeaderExtensions : { key: string; value: number }[]; + rtpListener: RtpListenerDump; + maxMessageSize: number; + dataProducerIds : string[]; + dataConsumerIds : string[]; + sctpParameters? : SctpParameters; + sctpState? : SctpState; + sctpListener?: SctpListenerDump; + traceEventTypes? : string[]; +}; + +export type BaseTransportStats = { + transportId: string; + timestamp: number; + sctpState?: SctpState; + bytesReceived: number; + recvBitrate: number; + bytesSent: number; + sendBitrate: number; + rtpBytesReceived: number; + rtpRecvBitrate: number; + rtpBytesSent: number; + rtpSendBitrate: number; + rtxBytesReceived: number; + rtxRecvBitrate: number; + rtxBytesSent: number; + rtxSendBitrate: number; + probationBytesSent: number; + probationSendBitrate: number; + availableOutgoingBitrate?: number; + availableIncomingBitrate?: number; + maxIncomingBitrate?: number; +}; + type TransportData = | WebRtcTransportData | PlainTransportData | PipeTransportData | DirectTransportData; +type RtpListenerDump = { + ssrcTable : {key: number; value: string}[]; + midTable : {key: number; value: string}[]; + ridTable : {key: number; value: string}[]; +}; + +type SctpListenerDump = { + streamIdTable : {key: number; value: string}[]; +}; + const logger = new Logger('Transport'); export class Transport @@ -151,9 +222,6 @@ export class Transport // Channel instance. protected readonly channel: Channel; - // PayloadChannel instance. - protected readonly payloadChannel: PayloadChannel; - // Close flag. #closed = false; @@ -206,7 +274,6 @@ export class Transport internal, data, channel, - payloadChannel, appData, getRouterRtpCapabilities, getProducerById, @@ -221,7 +288,6 @@ export class Transport this.internal = internal; this.#data = data; this.channel = channel; - this.payloadChannel = payloadChannel; this.#appData = appData || {} as TransportAppData; this.#getRouterRtpCapabilities = getRouterRtpCapabilities; this.getProducerById = getProducerById; @@ -293,12 +359,18 @@ export class Transport // Remove notification subscriptions. this.channel.removeAllListeners(this.internal.transportId); - this.payloadChannel.removeAllListeners(this.internal.transportId); - const reqData = { transportId: this.internal.transportId }; + /* Build Request. */ + const requestOffset = new FbsRouter.CloseTransportRequestT( + this.internal.transportId + ).pack(this.channel.bufferBuilder); - this.channel.request('router.closeTransport', this.internal.routerId, reqData) - .catch(() => {}); + this.channel.request( + FbsRequest.Method.ROUTER_CLOSE_TRANSPORT, + FbsRequest.Body.FBS_Router_CloseTransportRequest, + requestOffset, + this.internal.routerId + ).catch(() => {}); // Close every Producer. for (const producer of this.#producers.values()) @@ -359,7 +431,6 @@ export class Transport // Remove notification subscriptions. this.channel.removeAllListeners(this.internal.transportId); - this.payloadChannel.removeAllListeners(this.internal.transportId); // Close every Producer. for (const producer of this.#producers.values()) @@ -420,7 +491,6 @@ export class Transport // Remove notification subscriptions. this.channel.removeAllListeners(this.internal.transportId); - this.payloadChannel.removeAllListeners(this.internal.transportId); // Close every Producer. for (const producer of this.#producers.values()) @@ -469,12 +539,13 @@ export class Transport /** * Dump Transport. + * + * @abstract */ async dump(): Promise { - logger.debug('dump()'); - - return this.channel.request('transport.dump', this.internal.transportId); + // Should not happen. + throw new Error('method not implemented in the subclass'); } /** @@ -507,10 +578,16 @@ export class Transport { logger.debug('setMaxIncomingBitrate() [bitrate:%s]', bitrate); - const reqData = { bitrate }; + /* Build Request. */ + const requestOffset = FbsTransport.SetMaxIncomingBitrateRequest + .createSetMaxIncomingBitrateRequest(this.channel.bufferBuilder, bitrate); await this.channel.request( - 'transport.setMaxIncomingBitrate', this.internal.transportId, reqData); + FbsRequest.Method.TRANSPORT_SET_MAX_INCOMING_BITRATE, + FbsRequest.Body.FBS_Transport_SetMaxIncomingBitrateRequest, + requestOffset, + this.internal.transportId + ); } /** @@ -520,10 +597,17 @@ export class Transport { logger.debug('setMaxOutgoingBitrate() [bitrate:%s]', bitrate); - const reqData = { bitrate }; + /* Build Request. */ + const requestOffset = new FbsTransport.SetMaxOutgoingBitrateRequestT( + bitrate + ).pack(this.channel.bufferBuilder); await this.channel.request( - 'transport.setMaxOutgoingBitrate', this.internal.transportId, reqData); + FbsRequest.Method.TRANSPORT_SET_MAX_OUTGOING_BITRATE, + FbsRequest.Body.FBS_Transport_SetMaxOutgoingBitrateRequest, + requestOffset, + this.internal.transportId + ); } /** @@ -533,10 +617,17 @@ export class Transport { logger.debug('setMinOutgoingBitrate() [bitrate:%s]', bitrate); - const reqData = { bitrate }; + /* Build Request. */ + const requestOffset = new FbsTransport.SetMinOutgoingBitrateRequestT( + bitrate + ).pack(this.channel.bufferBuilder); await this.channel.request( - 'transport.setMinOutgoingBitrate', this.internal.transportId, reqData); + FbsRequest.Method.TRANSPORT_SET_MIN_OUTGOING_BITRATE, + FbsRequest.Body.FBS_Transport_SetMinOutgoingBitrateRequest, + requestOffset, + this.internal.transportId + ); } /** @@ -613,24 +704,36 @@ export class Transport const consumableRtpParameters = ortc.getConsumableRtpParameters( kind, rtpParameters, routerRtpCapabilities, rtpMapping); - const reqData = - { - producerId : id || uuidv4(), + const producerId = id || uuidv4(); + const requestOffset = createProduceRequest({ + builder : this.channel.bufferBuilder, + producerId, kind, rtpParameters, rtpMapping, keyFrameRequestDelay, paused - }; + }); - const status = - await this.channel.request('transport.produce', this.internal.transportId, reqData); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_PRODUCE, + FbsRequest.Body.FBS_Transport_ProduceRequest, + requestOffset, + this.internal.transportId + ); + + /* Decode Response. */ + const produceResponse = new FbsTransport.ProduceResponse(); + + response.body(produceResponse); + + const status = produceResponse.unpack(); const data = { kind, rtpParameters, - type : status.type, + type : utils.getProducerType(status.type), consumableRtpParameters }; @@ -639,11 +742,10 @@ export class Transport internal : { ...this.internal, - producerId : reqData.producerId + producerId }, data, channel : this.channel, - payloadChannel : this.payloadChannel, appData, paused }); @@ -745,21 +847,31 @@ export class Transport } } - const reqData = - { - consumerId : uuidv4(), - producerId, - kind : producer.kind, + const consumerId = uuidv4(); + const consumeRequestOffset = createConsumeRequest({ + builder : this.channel.bufferBuilder, + producer, + consumerId, rtpParameters, - type : pipe ? 'pipe' : producer.type, - consumableRtpEncodings : producer.consumableRtpParameters.encodings, paused, preferredLayers, - ignoreDtx - }; + ignoreDtx, + pipe + }); + + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_CONSUME, + FbsRequest.Body.FBS_Transport_ConsumeRequest, + consumeRequestOffset, + this.internal.transportId + ); - const status = - await this.channel.request('transport.consume', this.internal.transportId, reqData); + /* Decode Response. */ + const consumeResponse = new FbsTransport.ConsumeResponse(); + + response.body(consumeResponse); + + const status = consumeResponse.unpack(); const data = { @@ -774,16 +886,22 @@ export class Transport internal : { ...this.internal, - consumerId : reqData.consumerId + consumerId }, data, channel : this.channel, - payloadChannel : this.payloadChannel, appData, paused : status.paused, producerPaused : status.producerPaused, - score : status.score, - preferredLayers : status.preferredLayers + score : status.score ?? undefined, + preferredLayers : status.preferredLayers ? + { + spatialLayer : status.preferredLayers.spatialLayer, + temporalLayer : status.preferredLayers.temporalLayer !== null ? + status.preferredLayers.temporalLayer : + undefined + } : + undefined }); this.consumers.set(consumer.id, consumer); @@ -842,28 +960,38 @@ export class Transport } } - const reqData = - { - dataProducerId : id || uuidv4(), + const dataProducerId = id || uuidv4(); + const requestOffset = createProduceDataRequest({ + builder : this.channel.bufferBuilder, + dataProducerId, type, sctpStreamParameters, label, protocol - }; + }); - const data = - await this.channel.request('transport.produceData', this.internal.transportId, reqData); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_PRODUCE_DATA, + FbsRequest.Body.FBS_Transport_ProduceDataRequest, + requestOffset, + this.internal.transportId + ); + + /* Decode Response. */ + const produceResponse = new FbsDataProducer.DumpResponse(); + response.body(produceResponse); + + const data = parseDataProducerDump(produceResponse); const dataProducer = new DataProducer( { internal : { ...this.internal, - dataProducerId : reqData.dataProducerId + dataProducerId }, data, channel : this.channel, - payloadChannel : this.payloadChannel, appData }); @@ -964,30 +1092,40 @@ export class Transport } const { label, protocol } = dataProducer; + const dataConsumerId = uuidv4(); - const reqData = - { - dataConsumerId : uuidv4(), + const requestOffset = createConsumeDataRequest({ + builder : this.channel.bufferBuilder, + dataConsumerId, dataProducerId, type, sctpStreamParameters, label, protocol - }; + }); - const data = - await this.channel.request('transport.consumeData', this.internal.transportId, reqData); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_CONSUME_DATA, + FbsRequest.Body.FBS_Transport_ConsumeDataRequest, + requestOffset, + this.internal.transportId + ); + + /* Decode Response. */ + const consumeResponse = new FbsDataConsumer.DumpResponse(); + + response.body(consumeResponse); + const data = parseDataConsumerDump(consumeResponse); const dataConsumer = new DataConsumer( { internal : { ...this.internal, - dataConsumerId : reqData.dataConsumerId + dataConsumerId }, data, channel : this.channel, - payloadChannel : this.payloadChannel, appData }); @@ -1022,12 +1160,28 @@ export class Transport */ async enableTraceEvent(types: TransportTraceEventType[] = []): Promise { - logger.debug('pause()'); + logger.debug('enableTraceEvent()'); + + if (!Array.isArray(types)) + { + throw new TypeError('types must be an array'); + } + if (types.find((type) => typeof type !== 'string')) + { + throw new TypeError('every type must be a string'); + } - const reqData = { types }; + /* Build Request. */ + const requestOffset = new FbsTransport.EnableTraceEventRequestT( + types + ).pack(this.channel.bufferBuilder); await this.channel.request( - 'transport.enableTraceEvent', this.internal.transportId, reqData); + FbsRequest.Method.TRANSPORT_ENABLE_TRACE_EVENT, + FbsRequest.Body.FBS_Transport_EnableTraceEventRequest, + requestOffset, + this.internal.transportId + ); } private getNextSctpStreamId(): number @@ -1064,3 +1218,420 @@ export class Transport throw new Error('no sctpStreamId available'); } } + +export function fbsSctpState2StcpState(fbsSctpState: FbsSctpState): SctpState +{ + switch (fbsSctpState) + { + case FbsSctpState.NEW: + return 'new'; + case FbsSctpState.CONNECTING: + return 'connecting'; + case FbsSctpState.CONNECTED: + return 'connected'; + case FbsSctpState.FAILED: + return 'failed'; + case FbsSctpState.CLOSED: + return 'closed'; + default: + throw new TypeError(`invalid SctpState: ${fbsSctpState}`); + } +} + +export function parseTuple(binary: FbsTransport.Tuple): TransportTuple +{ + return { + localIp : binary.localIp()!, + localPort : binary.localPort(), + remoteIp : binary.remoteIp() ?? undefined, + remotePort : binary.remotePort(), + protocol : binary.protocol()! as TransportProtocol + }; +} + +export function parseBaseTransportDump( + binary: FbsTransport.Dump +): BaseTransportDump +{ + // Retrieve producerIds. + const producerIds = utils.parseVector(binary, 'producerIds'); + // Retrieve consumerIds. + const consumerIds = utils.parseVector(binary, 'consumerIds'); + // Retrieve map SSRC consumerId. + const mapSsrcConsumerId = utils.parseUint32StringVector(binary, 'mapSsrcConsumerId'); + // Retrieve map RTX SSRC consumerId. + const mapRtxSsrcConsumerId = utils.parseUint32StringVector(binary, 'mapRtxSsrcConsumerId'); + // Retrieve dataProducerIds. + const dataProducerIds = utils.parseVector(binary, 'dataProducerIds'); + // Retrieve dataConsumerIds. + const dataConsumerIds = utils.parseVector(binary, 'dataConsumerIds'); + // Retrieve recvRtpHeaderExtesions. + const recvRtpHeaderExtensions = utils.parseStringUint8Vector(binary, 'recvRtpHeaderExtensions'); + // Retrieve RtpListener. + const rtpListener = parseRtpListenerDump(binary.rtpListener()!); + + // Retrieve SctpParameters. + const fbsSctpParameters = binary.sctpParameters(); + let sctpParameters: SctpParameters | undefined; + + if (fbsSctpParameters) + { + sctpParameters = parseSctpParametersDump(fbsSctpParameters); + } + + // Retrieve sctpState. + const sctpState = binary.sctpState() === '' ? undefined : binary.sctpState() as SctpState; + + // Retrive sctpListener. + const sctpListener = binary.sctpListener() ? + parseSctpListenerDump(binary.sctpListener()!) : + undefined; + + // Retrieve traceEventTypes. + const traceEventTypes = utils.parseVector(binary, 'traceEventTypes'); + + return { + id : binary.id()!, + direct : binary.direct(), + producerIds : producerIds, + consumerIds : consumerIds, + mapSsrcConsumerId : mapSsrcConsumerId, + mapRtxSsrcConsumerId : mapRtxSsrcConsumerId, + dataProducerIds : dataProducerIds, + dataConsumerIds : dataConsumerIds, + recvRtpHeaderExtensions : recvRtpHeaderExtensions, + rtpListener : rtpListener, + maxMessageSize : binary.maxMessageSize(), + sctpParameters : sctpParameters, + sctpState : sctpState, + sctpListener : sctpListener, + traceEventTypes : traceEventTypes + }; +} + +export function parseBaseTransportStats( + binary: FbsTransport.Stats +): BaseTransportStats +{ + const sctpState = binary.sctpState() === '' ? undefined : binary.sctpState() as SctpState; + + return { + transportId : binary.transportId()!, + timestamp : Number(binary.timestamp()), + sctpState, + bytesReceived : Number(binary.bytesReceived()), + recvBitrate : Number(binary.recvBitrate()), + bytesSent : Number(binary.bytesSent()), + sendBitrate : Number(binary.sendBitrate()), + rtpBytesReceived : Number(binary.rtpBytesReceived()), + rtpRecvBitrate : Number(binary.rtpRecvBitrate()), + rtpBytesSent : Number(binary.rtpBytesSent()), + rtpSendBitrate : Number(binary.rtpSendBitrate()), + rtxBytesReceived : Number(binary.rtxBytesReceived()), + rtxRecvBitrate : Number(binary.rtxRecvBitrate()), + rtxBytesSent : Number(binary.rtxBytesSent()), + rtxSendBitrate : Number(binary.rtxSendBitrate()), + probationBytesSent : Number(binary.probationBytesSent()), + probationSendBitrate : Number(binary.probationSendBitrate()), + availableOutgoingBitrate : Number(binary.availableOutgoingBitrate()), + availableIncomingBitrate : Number(binary.availableIncomingBitrate()), + maxIncomingBitrate : binary.maxIncomingBitrate() ? + Number(binary.maxIncomingBitrate()) : + undefined + }; +} + +export function parseTransportTraceEventData( + trace: FbsTransport.TraceNotification +): TransportTraceEventData +{ + switch (trace.type()) + { + case FbsTransport.TraceType.BWE: + { + const info = new FbsTransport.BweTraceInfo(); + + trace.info(info); + + return { + type : 'bwe', + timestamp : Number(trace.timestamp()), + direction : trace.direction() === FbsTransport.TraceDirection.DIRECTION_IN ? 'in' : 'out', + info : parseBweTraceInfo(info!) + }; + } + + case FbsTransport.TraceType.PROBATION: + { + return { + type : 'probation', + timestamp : Number(trace.timestamp()), + direction : trace.direction() === FbsTransport.TraceDirection.DIRECTION_IN ? 'in' : 'out', + info : {} + }; + } + } +} + +function parseBweTraceInfo(binary: FbsTransport.BweTraceInfo): +{ + desiredBitrate:number; + effectiveDesiredBitrate:number; + minBitrate:number; + maxBitrate:number; + startBitrate:number; + maxPaddingBitrate:number; + availableBitrate:number; + bweType:'transport-cc' | 'remb'; +} +{ + return { + desiredBitrate : binary.desiredBitrate(), + effectiveDesiredBitrate : binary.effectiveDesiredBitrate(), + minBitrate : binary.minBitrate(), + maxBitrate : binary.maxBitrate(), + startBitrate : binary.startBitrate(), + maxPaddingBitrate : binary.maxPaddingBitrate(), + availableBitrate : binary.availableBitrate(), + bweType : binary.bweType() === FbsTransport.BweType.TRANSPORT_CC ? + 'transport-cc' : + 'remb' + }; +} + +function createConsumeRequest({ + builder, + producer, + consumerId, + rtpParameters, + paused, + preferredLayers, + ignoreDtx, + pipe +} : { + builder: flatbuffers.Builder; + producer: Producer; + consumerId: string; + rtpParameters: RtpParameters; + paused: boolean; + preferredLayers?: ConsumerLayers; + ignoreDtx?: boolean; + pipe: boolean; +}): number +{ + const rtpParametersOffset = serializeRtpParameters(builder, rtpParameters); + const consumerIdOffset = builder.createString(consumerId); + const producerIdOffset = builder.createString(producer.id); + let consumableRtpEncodingsOffset: number | undefined; + let preferredLayersOffset: number | undefined; + + if (producer.consumableRtpParameters.encodings) + { + consumableRtpEncodingsOffset = serializeRtpEncodingParameters( + builder, producer.consumableRtpParameters.encodings + ); + } + + if (preferredLayers) + { + FbsConsumer.ConsumerLayers.startConsumerLayers(builder); + FbsConsumer.ConsumerLayers.addSpatialLayer(builder, preferredLayers.spatialLayer); + + if (preferredLayers.temporalLayer !== undefined) + { + FbsConsumer.ConsumerLayers.addTemporalLayer( + builder, preferredLayers.temporalLayer + ); + } + + preferredLayersOffset = FbsConsumer.ConsumerLayers.endConsumerLayers(builder); + } + + const ConsumeRequest = FbsTransport.ConsumeRequest; + + // Create Consume Request. + ConsumeRequest.startConsumeRequest(builder); + ConsumeRequest.addConsumerId(builder, consumerIdOffset); + ConsumeRequest.addProducerId(builder, producerIdOffset); + ConsumeRequest.addKind( + builder, producer.kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO); + ConsumeRequest.addRtpParameters(builder, rtpParametersOffset); + ConsumeRequest.addType( + builder, + utils.getRtpParametersType(producer.type, pipe) + ); + + if (consumableRtpEncodingsOffset) + { + ConsumeRequest.addConsumableRtpEncodings(builder, consumableRtpEncodingsOffset); + } + + ConsumeRequest.addPaused(builder, paused); + + if (preferredLayersOffset) + { + ConsumeRequest.addPreferredLayers(builder, preferredLayersOffset); + } + + ConsumeRequest.addIgnoreDtx(builder, Boolean(ignoreDtx)); + + return ConsumeRequest.endConsumeRequest(builder); +} + +function createProduceRequest({ + builder, + producerId, + kind, + rtpParameters, + rtpMapping, + keyFrameRequestDelay, + paused +} : { + builder : flatbuffers.Builder; + producerId: string; + kind: MediaKind; + rtpParameters: RtpParameters; + rtpMapping: ortc.RtpMapping; + keyFrameRequestDelay?: number; + paused: boolean; +}): number +{ + const producerIdOffset = builder.createString(producerId); + const rtpParametersOffset = serializeRtpParameters(builder, rtpParameters); + const rtpMappingOffset = ortc.serializeRtpMapping(builder, rtpMapping); + + FbsTransport.ProduceRequest.startProduceRequest(builder); + FbsTransport.ProduceRequest.addProducerId(builder, producerIdOffset); + FbsTransport.ProduceRequest.addKind( + builder, kind === 'audio' ? FbsMediaKind.AUDIO : FbsMediaKind.VIDEO); + FbsTransport.ProduceRequest.addRtpParameters(builder, rtpParametersOffset); + FbsTransport.ProduceRequest.addRtpMapping(builder, rtpMappingOffset); + FbsTransport.ProduceRequest.addKeyFrameRequestDelay(builder, keyFrameRequestDelay ?? 0); + FbsTransport.ProduceRequest.addPaused(builder, paused); + + return FbsTransport.ProduceRequest.endProduceRequest(builder); +} + +function createProduceDataRequest({ + builder, + dataProducerId, + type, + sctpStreamParameters, + label, + protocol +} : { + builder : flatbuffers.Builder; + dataProducerId: string; + type: DataProducerType; + sctpStreamParameters?: SctpStreamParameters; + label: string; + protocol: string; +}): number +{ + const dataProducerIdOffset = builder.createString(dataProducerId); + const typeOffset = builder.createString(type); + const labelOffset = builder.createString(label); + const protocolOffset = builder.createString(protocol); + + let sctpStreamParametersOffset = 0; + + if (sctpStreamParameters) + { + sctpStreamParametersOffset = serializeSctpStreamParameters( + builder, sctpStreamParameters + ); + } + + FbsTransport.ProduceDataRequest.startProduceDataRequest(builder); + FbsTransport.ProduceDataRequest.addDataProducerId(builder, dataProducerIdOffset); + FbsTransport.ProduceDataRequest.addType(builder, typeOffset); + + if (sctpStreamParametersOffset) + { + FbsTransport.ProduceDataRequest.addSctpStreamParameters( + builder, sctpStreamParametersOffset + ); + } + + FbsTransport.ProduceDataRequest.addLabel(builder, labelOffset); + FbsTransport.ProduceDataRequest.addProtocol(builder, protocolOffset); + + return FbsTransport.ProduceDataRequest.endProduceDataRequest(builder); +} + +function createConsumeDataRequest({ + builder, + dataConsumerId, + dataProducerId, + type, + sctpStreamParameters, + label, + protocol +} : { + builder : flatbuffers.Builder; + dataConsumerId: string; + dataProducerId: string; + type: DataConsumerType; + sctpStreamParameters?: SctpStreamParameters; + label: string; + protocol: string; +}): number +{ + const dataConsumerIdOffset = builder.createString(dataConsumerId); + const dataProducerIdOffset = builder.createString(dataProducerId); + const typeOffset = builder.createString(type); + const labelOffset = builder.createString(label); + const protocolOffset = builder.createString(protocol); + + let sctpStreamParametersOffset = 0; + + if (sctpStreamParameters) + { + sctpStreamParametersOffset = serializeSctpStreamParameters( + builder, sctpStreamParameters + ); + } + + FbsTransport.ConsumeDataRequest.startConsumeDataRequest(builder); + FbsTransport.ConsumeDataRequest.addDataConsumerId(builder, dataConsumerIdOffset); + FbsTransport.ConsumeDataRequest.addDataProducerId(builder, dataProducerIdOffset); + FbsTransport.ConsumeDataRequest.addType(builder, typeOffset); + + if (sctpStreamParametersOffset) + { + FbsTransport.ConsumeDataRequest.addSctpStreamParameters( + builder, sctpStreamParametersOffset + ); + } + + FbsTransport.ConsumeDataRequest.addLabel(builder, labelOffset); + FbsTransport.ConsumeDataRequest.addProtocol(builder, protocolOffset); + + return FbsTransport.ConsumeDataRequest.endConsumeDataRequest(builder); +} + +function parseRtpListenerDump(binary: FbsTransport.RtpListener): RtpListenerDump +{ + // Retrieve ssrcTable. + const ssrcTable = utils.parseUint32StringVector(binary, 'ssrcTable'); + // Retrieve midTable. + const midTable = utils.parseUint32StringVector(binary, 'midTable'); + // Retrieve ridTable. + const ridTable = utils.parseUint32StringVector(binary, 'ridTable'); + + return { + ssrcTable, + midTable, + ridTable + }; +} + +function parseSctpListenerDump(binary: FbsTransport.SctpListener): SctpListenerDump +{ + // Retrieve streamIdTable. + const streamIdTable = utils.parseUint32StringVector(binary, 'streamIdTable'); + + return { + streamIdTable + }; +} diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index 0db3346ded..31e10f922d 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -4,6 +4,9 @@ import { Channel } from './Channel'; import { TransportProtocol } from './Transport'; import { WebRtcTransport } from './WebRtcTransport'; import { AppData } from './types'; +import { Body as RequestBody, Method } from './fbs/request'; +import * as FbsWorker from './fbs/worker'; +import * as FbsWebRtcServer from './fbs/web-rtc-server'; export type WebRtcServerOptions = { @@ -172,9 +175,14 @@ export class WebRtcServer this.#closed = true; - const reqData = { webRtcServerId: this.#internal.webRtcServerId }; + // Build the request. + const requestOffset = new FbsWorker.CloseWebRtcServerRequestT( + this.#internal.webRtcServerId).pack(this.#channel.bufferBuilder); - this.#channel.request('worker.closeWebRtcServer', undefined, reqData) + this.#channel.request( + Method.WORKER_WEBRTC_SERVER_CLOSE, + RequestBody.FBS_Worker_CloseWebRtcServerRequest, + requestOffset) .catch(() => {}); // Close every WebRtcTransport. @@ -226,7 +234,15 @@ export class WebRtcServer { logger.debug('dump()'); - return this.#channel.request('webRtcServer.dump', this.#internal.webRtcServerId); + const response = await this.#channel.request( + Method.WEBRTC_SERVER_DUMP, undefined, undefined, this.#internal.webRtcServerId); + + /* Decode Response. */ + const dump = new FbsWebRtcServer.DumpResponse(); + + response.body(dump); + + return dump.unpack(); } /** diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index e297a5d4a1..c5e43b9092 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -1,10 +1,17 @@ +import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; import { + fbsSctpState2StcpState, + parseBaseTransportDump, + parseBaseTransportStats, + parseTransportTraceEventData, + parseTuple, + BaseTransportDump, + BaseTransportStats, Transport, TransportListenIp, TransportProtocol, TransportTuple, - TransportTraceEventData, TransportEvents, TransportObserverEvents, TransportConstructorOptions, @@ -12,8 +19,14 @@ import { } from './Transport'; import { WebRtcServer } from './WebRtcServer'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; -import { Either } from './utils'; import { AppData } from './types'; +import { Either, parseVector } from './utils'; +import { Event, Notification } from './fbs/notification'; +import * as FbsRequest from './fbs/request'; +import * as FbsTransport from './fbs/transport'; +import * as FbsWebRtcTransport from './fbs/web-rtc-transport'; +import { DtlsState as FbsDtlsState } from './fbs/web-rtc-transport/dtls-state'; +import { IceState as FbsIceState } from './fbs/web-rtc-transport/ice-state'; export type WebRtcTransportOptions = WebRtcTransportOptionsBase & WebRtcTransportListen; @@ -141,31 +154,9 @@ export type DtlsRole = 'auto' | 'client' | 'server'; export type DtlsState = 'new' | 'connecting' | 'connected' | 'failed' | 'closed'; -export type WebRtcTransportStat = +export type WebRtcTransportStat = BaseTransportStats & { - // Common to all Transports. type: string; - transportId: string; - timestamp: number; - sctpState?: SctpState; - bytesReceived: number; - recvBitrate: number; - bytesSent: number; - sendBitrate: number; - rtpBytesReceived: number; - rtpRecvBitrate: number; - rtpBytesSent: number; - rtpSendBitrate: number; - rtxBytesReceived: number; - rtxRecvBitrate: number; - rtxBytesSent: number; - rtxSendBitrate: number; - probationBytesSent: number; - probationSendBitrate: number; - availableOutgoingBitrate?: number; - availableIncomingBitrate?: number; - maxIncomingBitrate?: number; - // WebRtcTransport specific. iceRole: string; iceState: IceState; iceSelectedTuple?: TransportTuple; @@ -208,6 +199,18 @@ export type WebRtcTransportData = sctpState?: SctpState; }; +type WebRtcTransportDump = BaseTransportDump & +{ + iceRole: 'controlled'; + iceParameters: IceParameters; + iceCandidates: IceCandidate[]; + iceState: IceState; + iceSelectedTuple?: TransportTuple; + dtlsParameters: DtlsParameters; + dtlsState: DtlsState; + dtlsRemoteCert?: string; +}; + const logger = new Logger('WebRtcTransport'); export class WebRtcTransport @@ -397,6 +400,28 @@ export class WebRtcTransport super.listenServerClosed(); } + /** + * Dump Transport. + */ + async dump(): Promise + { + logger.debug('dump()'); + + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_DUMP, + undefined, + undefined, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsWebRtcTransport.DumpResponse(); + + response.body(data); + + return parseWebRtcTransportDumpResponse(data); + } + /** * Get WebRtcTransport stats. * @@ -406,7 +431,19 @@ export class WebRtcTransport { logger.debug('getStats()'); - return this.channel.request('transport.getStats', this.internal.transportId); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_GET_STATS, + undefined, + undefined, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsWebRtcTransport.GetStatsResponse(); + + response.body(data); + + return [ parseGetStatsResponse(data) ]; } /** @@ -418,13 +455,27 @@ export class WebRtcTransport { logger.debug('connect()'); - const reqData = { dtlsParameters }; + const requestOffset = createConnectRequest({ + builder : this.channel.bufferBuilder, + dtlsParameters + }); + + // Wait for response. + const response = await this.channel.request( + FbsRequest.Method.WEBRTC_TRANSPORT_CONNECT, + FbsRequest.Body.FBS_WebRtcTransport_ConnectRequest, + requestOffset, + this.internal.transportId + ); + + /* Decode Response. */ + const data = new FbsWebRtcTransport.ConnectResponse(); - const data = - await this.channel.request('transport.connect', this.internal.transportId, reqData); + response.body(data); // Update data. - this.#data.dtlsParameters.role = data.dtlsLocalRole; + this.#data.dtlsParameters.role = + data.dtlsLocalRole()! as DtlsRole; } /** @@ -434,10 +485,23 @@ export class WebRtcTransport { logger.debug('restartIce()'); - const data = - await this.channel.request('transport.restartIce', this.internal.transportId); + const response = await this.channel.request( + FbsRequest.Method.TRANSPORT_RESTART_ICE, + undefined, + undefined, + this.internal.transportId + ); - const { iceParameters } = data; + /* Decode Response. */ + const restartIceResponse = new FbsTransport.RestartIceResponse(); + + response.body(restartIceResponse); + + const iceParameters = { + usernameFragment : restartIceResponse.usernameFragment()!, + password : restartIceResponse.password()!, + iceLite : restartIceResponse.iceLite() + }; this.#data.iceParameters = iceParameters; @@ -446,13 +510,17 @@ export class WebRtcTransport private handleWorkerNotifications(): void { - this.channel.on(this.internal.transportId, (event: string, data?: any) => + this.channel.on(this.internal.transportId, (event: Event, data?: Notification) => { switch (event) { - case 'icestatechange': + case Event.WEBRTCTRANSPORT_ICE_STATE_CHANGE: { - const iceState = data.iceState as IceState; + const notification = new FbsWebRtcTransport.IceStateChangeNotification(); + + data!.body(notification); + + const iceState = fbsIceState2IceState(notification.iceState()); this.#data.iceState = iceState; @@ -464,9 +532,14 @@ export class WebRtcTransport break; } - case 'iceselectedtuplechange': + case Event.WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE: { - const iceSelectedTuple = data.iceSelectedTuple as TransportTuple; + const notification = + new FbsWebRtcTransport.IceSelectedTupleChangeNotification(); + + data!.body(notification); + + const iceSelectedTuple = parseTuple(notification.tuple()!); this.#data.iceSelectedTuple = iceSelectedTuple; @@ -478,16 +551,19 @@ export class WebRtcTransport break; } - case 'dtlsstatechange': + case Event.WEBRTCTRANSPORT_DTLS_STATE_CHANGE: { - const dtlsState = data.dtlsState as DtlsState; - const dtlsRemoteCert = data.dtlsRemoteCert as string; + const notification = new FbsWebRtcTransport.DtlsStateChangeNotification(); + + data!.body(notification); + + const dtlsState = fbsDtlsState2DtlsState(notification.dtlsState()); this.#data.dtlsState = dtlsState; if (dtlsState === 'connected') { - this.#data.dtlsRemoteCert = dtlsRemoteCert; + this.#data.dtlsRemoteCert = notification.remoteCert()!; } this.safeEmit('dtlsstatechange', dtlsState); @@ -498,9 +574,13 @@ export class WebRtcTransport break; } - case 'sctpstatechange': + case Event.TRANSPORT_SCTP_STATE_CHANGE: { - const sctpState = data.sctpState as SctpState; + const notification = new FbsTransport.SctpStateChangeNotification(); + + data!.body(notification); + + const sctpState = fbsSctpState2StcpState(notification.sctpState()); this.#data.sctpState = sctpState; @@ -512,9 +592,13 @@ export class WebRtcTransport break; } - case 'trace': + case Event.TRANSPORT_TRACE: { - const trace = data as TransportTraceEventData; + const notification = new FbsTransport.TraceNotification(); + + data!.body(notification); + + const trace = parseTransportTraceEventData(notification); this.safeEmit('trace', trace); @@ -532,3 +616,181 @@ export class WebRtcTransport }); } } + +export function fbsIceState2IceState(fbsIceState: FbsIceState): IceState +{ + switch (fbsIceState) + { + case FbsIceState.NEW: + return 'new'; + case FbsIceState.CONNECTED: + return 'connected'; + case FbsIceState.COMPLETED: + return 'completed'; + case FbsIceState.DISCONNECTED: + return 'disconnected'; + case FbsIceState.CLOSED: + return 'closed'; + default: + throw new TypeError(`invalid SctpState: ${fbsIceState}`); + } +} + +export function fbsDtlsState2DtlsState(fbsDtlsState: FbsDtlsState): DtlsState +{ + switch (fbsDtlsState) + { + case FbsDtlsState.NEW: + return 'new'; + case FbsDtlsState.CONNECTING: + return 'connecting'; + case FbsDtlsState.CONNECTED: + return 'connected'; + case FbsDtlsState.FAILED: + return 'failed'; + case FbsDtlsState.CLOSED: + return 'closed'; + default: + throw new TypeError(`invalid SctpState: ${fbsDtlsState}`); + } +} + +export function parseWebRtcTransportDumpResponse( + binary: FbsWebRtcTransport.DumpResponse +): WebRtcTransportDump +{ + // Retrieve BaseTransportDump. + const baseTransportDump = parseBaseTransportDump(binary.base()!); + // Retrieve ICE candidates. + const iceCandidates = parseVector(binary, 'iceCandidates', parseIceCandidate); + // Retrieve ICE parameters. + const iceParameters = parseIceParameters(binary.iceParameters()!); + // Retrieve DTLS parameters. + const dtlsParameters = parseDtlsParameters(binary.dtlsParameters()!); + + return { + ...baseTransportDump, + sctpParameters : baseTransportDump.sctpParameters, + sctpState : baseTransportDump.sctpState, + iceRole : 'controlled', + iceParameters : iceParameters, + iceCandidates : iceCandidates, + iceState : binary.iceState() as IceState, + dtlsParameters : dtlsParameters, + dtlsState : binary.dtlsState() as DtlsState + }; +} + +function createConnectRequest( + { + builder, + dtlsParameters + }: + { + builder : flatbuffers.Builder; + dtlsParameters: DtlsParameters; + } +): number +{ + // Serialize DtlsParameters. This can throw. + const dtlsParametersOffset = serializeDtlsParameters(builder, dtlsParameters); + + // Create request. + return FbsWebRtcTransport.ConnectRequest.createConnectRequest( + builder, + dtlsParametersOffset); +} + +function parseGetStatsResponse( + binary: FbsWebRtcTransport.GetStatsResponse +):WebRtcTransportStat +{ + const base = parseBaseTransportStats(binary.base()!); + + return { + ...base, + type : 'webrtc-transport', + iceRole : binary.iceRole()!, + iceState : binary.iceState() as IceState, + iceSelectedTuple : binary.iceSelectedTuple() ? + parseTuple(binary.iceSelectedTuple()!) : + undefined, + dtlsState : binary.dtlsState() as DtlsState + }; +} + +function parseIceCandidate(binary: FbsWebRtcTransport.IceCandidate): IceCandidate +{ + return { + foundation : binary.foundation()!, + priority : binary.priority(), + ip : binary.ip()!, + protocol : binary.protocol() as TransportProtocol, + port : binary.port(), + type : 'host', + tcpType : binary.tcpType() === 'passive' ? 'passive' : undefined + }; +} + +function parseIceParameters(binary: FbsWebRtcTransport.IceParameters): IceParameters +{ + return { + usernameFragment : binary.usernameFragment()!, + password : binary.password()!, + iceLite : binary.iceLite() + }; +} + +function parseDtlsParameters(binary: FbsWebRtcTransport.DtlsParameters): DtlsParameters +{ + const fingerprints: DtlsFingerprint[] = []; + + for (let i=0; i // Channel instance. readonly #channel: Channel; - // PayloadChannel instance. - readonly #payloadChannel: PayloadChannel; - // Closed flag. #closed = false; @@ -335,9 +348,7 @@ export class Worker // fd 2 (stderr) : Same as stdout. // fd 3 (channel) : Producer Channel fd. // fd 4 (channel) : Consumer Channel fd. - // fd 5 (channel) : Producer PayloadChannel fd. - // fd 6 (channel) : Consumer PayloadChannel fd. - stdio : [ 'ignore', 'pipe', 'pipe', 'pipe', 'pipe', 'pipe', 'pipe' ], + stdio : [ 'ignore', 'pipe', 'pipe', 'pipe', 'pipe' ], windowsHide : true }); @@ -350,23 +361,14 @@ export class Worker pid : this.#pid }); - this.#payloadChannel = new PayloadChannel( - { - // NOTE: TypeScript does not like more than 5 fds. - // @ts-ignore - producerSocket : this.#child.stdio[5], - // @ts-ignore - consumerSocket : this.#child.stdio[6] - }); - this.#appData = appData || {} as WorkerAppData; let spawnDone = false; // Listen for 'running' notification. - this.#channel.once(String(this.#pid), (event: string) => + this.#channel.once(String(this.#pid), (event: Event) => { - if (!spawnDone && event === 'running') + if (!spawnDone && event === Event.WORKER_RUNNING) { spawnDone = true; @@ -558,9 +560,6 @@ export class Worker // Close the Channel instance. this.#channel.close(); - // Close the PayloadChannel instance. - this.#payloadChannel.close(); - // Close every Router. for (const router of this.#routers) { @@ -586,7 +585,17 @@ export class Worker { logger.debug('dump()'); - return this.#channel.request('worker.dump'); + // Send the request and wait for the response. + const response = await this.#channel.request( + FbsRequest.Method.WORKER_DUMP + ); + + /* Decode Response. */ + const dump = new FbsWorker.DumpResponse(); + + response.body(dump); + + return dump.unpack(); } /** @@ -596,7 +605,37 @@ export class Worker { logger.debug('getResourceUsage()'); - return this.#channel.request('worker.getResourceUsage'); + const response = await this.#channel.request( + FbsRequest.Method.WORKER_GET_RESOURCE_USAGE + ); + + /* Decode Response. */ + const resourceUsage = new FbsWorker.ResourceUsageResponse(); + + response.body(resourceUsage); + + const ru = resourceUsage.unpack(); + + /* eslint-disable camelcase */ + return { + ru_utime : Number(ru.ruUtime), + ru_stime : Number(ru.ruStime), + ru_maxrss : Number(ru.ruMaxrss), + ru_ixrss : Number(ru.ruIxrss), + ru_idrss : Number(ru.ruIdrss), + ru_isrss : Number(ru.ruIsrss), + ru_minflt : Number(ru.ruMinflt), + ru_majflt : Number(ru.ruMajflt), + ru_nswap : Number(ru.ruNswap), + ru_inblock : Number(ru.ruInblock), + ru_oublock : Number(ru.ruOublock), + ru_msgsnd : Number(ru.ruMsgsnd), + ru_msgrcv : Number(ru.ruMsgrcv), + ru_nsignals : Number(ru.ruNsignals), + ru_nvcsw : Number(ru.ruNvcsw), + ru_nivcsw : Number(ru.ruNivcsw) + }; + /* eslint-enable camelcase */ } /** @@ -611,9 +650,15 @@ export class Worker { logger.debug('updateSettings()'); - const reqData = { logLevel, logTags }; + // Build the request. + const requestOffset = new FbsWorker.UpdateSettingsRequestT(logLevel, logTags) + .pack(this.#channel.bufferBuilder); - await this.#channel.request('worker.updateSettings', undefined, reqData); + await this.#channel.request( + FbsRequest.Method.WORKER_UPDATE_SETTINGS, + FbsRequest.Body.FBS_Worker_UpdateSettingsRequest, + requestOffset + ); } /** @@ -633,17 +678,42 @@ export class Worker throw new TypeError('if given, appData must be an object'); } - const reqData = + // Build the request. + const fbsListenInfos: FbsWebRtcServer.ListenInfoT[] = []; + + for (const listenInfo of listenInfos) { - webRtcServerId : uuidv4(), - listenInfos - }; + fbsListenInfos.push(new FbsWebRtcServer.ListenInfoT( + listenInfo.protocol === 'udp' ? FbsTransportProtocol.UDP : FbsTransportProtocol.TCP, + listenInfo.ip, + listenInfo.announcedIp, + listenInfo.port) + ); + } + + const webRtcServerId = uuidv4(); + + let createWebRtcServerRequestOffset; + + try + { + createWebRtcServerRequestOffset = new FbsWorker.CreateWebRtcServerRequestT( + webRtcServerId, fbsListenInfos).pack(this.#channel.bufferBuilder); + } + catch (error) + { + throw new TypeError((error as Error).message); + } - await this.#channel.request('worker.createWebRtcServer', undefined, reqData); + await this.#channel.request( + FbsRequest.Method.WORKER_CREATE_WEBRTC_SERVER, + FbsRequest.Body.FBS_Worker_CreateWebRtcServerRequest, + createWebRtcServerRequestOffset + ); const webRtcServer = new WebRtcServer( { - internal : { webRtcServerId: reqData.webRtcServerId }, + internal : { webRtcServerId }, channel : this.#channel, appData }); @@ -676,20 +746,24 @@ export class Worker // This may throw. const rtpCapabilities = ortc.generateRouterRtpCapabilities(mediaCodecs); - const reqData = { routerId: uuidv4() }; + const routerId = uuidv4(); + + // Get flatbuffer builder. + const createRouterRequestOffset = + new FbsWorker.CreateRouterRequestT(routerId).pack(this.#channel.bufferBuilder); - await this.#channel.request('worker.createRouter', undefined, reqData); + await this.#channel.request(FbsRequest.Method.WORKER_CREATE_ROUTER, + FbsRequest.Body.FBS_Worker_CreateRouterRequest, createRouterRequestOffset); const data = { rtpCapabilities }; const router = new Router( { internal : { - routerId : reqData.routerId + routerId }, data, channel : this.#channel, - payloadChannel : this.#payloadChannel, appData }); @@ -717,9 +791,6 @@ export class Worker // Close the Channel instance. this.#channel.close(); - // Close the PayloadChannel instance. - this.#payloadChannel.close(); - // Close every Router. for (const router of this.#routers) { diff --git a/node/src/ortc.ts b/node/src/ortc.ts index 6f229e6743..b12b8c4e1b 100644 --- a/node/src/ortc.ts +++ b/node/src/ortc.ts @@ -1,4 +1,5 @@ import * as h264 from 'h264-profile-level-id'; +import * as flatbuffers from 'flatbuffers'; import * as utils from './utils'; import { UnsupportedError } from './errors'; import { supportedRtpCapabilities } from './supportedRtpCapabilities'; @@ -21,8 +22,9 @@ import { SctpParameters, SctpStreamParameters } from './SctpParameters'; +import * as FbsRtpParameters from './fbs/rtp-parameters'; -type RtpMapping = +export type RtpMapping = { codecs: { @@ -1061,8 +1063,7 @@ export function getConsumableRtpParameters( consumableParams.rtcp = { cname : params.rtcp!.cname, - reducedSize : true, - mux : true + reducedSize : true }; return consumableParams; @@ -1517,3 +1518,39 @@ function matchCodecs( return true; } + +export function serializeRtpMapping( + builder: flatbuffers.Builder, rtpMapping: RtpMapping +): number +{ + const codecs: number[] = []; + + for (const codec of rtpMapping.codecs) + { + codecs.push( + FbsRtpParameters.CodecMapping.createCodecMapping( + builder, codec.payloadType, codec.mappedPayloadType) + ); + } + const codecsOffset = + FbsRtpParameters.RtpMapping.createCodecsVector(builder, codecs); + + const encodings: number[] = []; + + for (const encoding of rtpMapping.encodings) + { + encodings.push( + FbsRtpParameters.EncodingMapping.createEncodingMapping( + builder, + builder.createString(encoding.rid), + encoding.ssrc ?? null, + builder.createString(encoding.scalabilityMode), + encoding.mappedSsrc) + ); + } + const encodingsOffset = + FbsRtpParameters.RtpMapping.createEncodingsVector(builder, encodings); + + return FbsRtpParameters.RtpMapping.createRtpMapping( + builder, codecsOffset, encodingsOffset); +} diff --git a/node/src/tests/test-Consumer.ts b/node/src/tests/test-Consumer.ts index 156eb76535..dec72f88b5 100644 --- a/node/src/tests/test-Consumer.ts +++ b/node/src/tests/test-Consumer.ts @@ -1,5 +1,8 @@ +import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; import { UnsupportedError } from '../errors'; +import { Notification, Body as NotificationBody, Event } from '../fbs/notification'; +import * as FbsConsumer from '../fbs/consumer'; const { createWorker } = mediasoup; @@ -317,13 +320,17 @@ test('transport.consume() succeeds', async () => expect(audioConsumer.currentLayers).toBeUndefined(); expect(audioConsumer.appData).toEqual({ baz: 'LOL' }); - await expect(router.dump()) - .resolves - .toMatchObject( - { - mapProducerIdConsumerIds : { [audioProducer.id]: [ audioConsumer.id ] }, - mapConsumerIdProducerId : { [audioConsumer.id]: audioProducer.id } - }); + let dump = await router.dump(); + + expect(dump.mapProducerIdConsumerIds) + .toEqual(expect.arrayContaining([ + { key: audioProducer.id, values: [ audioConsumer.id ] } + ])); + + expect(dump.mapConsumerIdProducerId) + .toEqual(expect.arrayContaining([ + { key: audioConsumer.id, value: audioProducer.id } + ])); await expect(transport2.dump()) .resolves @@ -462,27 +469,36 @@ test('transport.consume() succeeds', async () => expect(videoPipeConsumer.currentLayers).toBeUndefined(); expect(videoPipeConsumer.appData).toBeUndefined; - const dump = await router.dump(); + dump = await router.dump(); - for (const key of Object.keys(dump.mapProducerIdConsumerIds)) + // Sort values for mapProducerIdConsumerIds. + expect(Array.isArray(dump.mapProducerIdConsumerIds)).toBe(true); + dump.mapProducerIdConsumerIds.forEach((entry: any) => { - dump.mapProducerIdConsumerIds[key] = dump.mapProducerIdConsumerIds[key].sort(); - } + entry.values = entry.values.sort(); + }); - expect(dump).toMatchObject( - { - mapProducerIdConsumerIds : - { - [audioProducer.id] : [ audioConsumer.id ], - [videoProducer.id] : [ videoConsumer.id, videoPipeConsumer.id ].sort() - }, - mapConsumerIdProducerId : - { - [audioConsumer.id] : audioProducer.id, - [videoConsumer.id] : videoProducer.id, - [videoPipeConsumer.id] : videoProducer.id - } - }); + expect(dump.mapProducerIdConsumerIds) + .toEqual(expect.arrayContaining([ + { key: audioProducer.id, values: [ audioConsumer.id ] } + ])); + expect(dump.mapProducerIdConsumerIds) + .toEqual(expect.arrayContaining([ + { key: videoProducer.id, values: [ videoConsumer.id, videoPipeConsumer.id ].sort() } + ])); + + expect(dump.mapConsumerIdProducerId) + .toEqual(expect.arrayContaining([ + { key: audioConsumer.id, value: audioProducer.id } + ])); + expect(dump.mapConsumerIdProducerId) + .toEqual(expect.arrayContaining([ + { key: videoConsumer.id, value: videoProducer.id } + ])); + expect(dump.mapConsumerIdProducerId) + .toEqual(expect.arrayContaining([ + { key: videoPipeConsumer.id, value: videoProducer.id } + ])); await expect(transport2.dump()) .resolves @@ -641,7 +657,7 @@ test('consumer.dump() succeeds', async () => }); expect(data.rtpParameters.codecs[0].rtcpFeedback).toEqual([]); expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); - expect(data.rtpParameters.headerExtensions.length).toBe(3); + expect(data.rtpParameters.headerExtensions!.length).toBe(3); expect(data.rtpParameters.headerExtensions).toEqual( [ { @@ -664,20 +680,22 @@ test('consumer.dump() succeeds', async () => } ]); expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); - expect(data.rtpParameters.encodings.length).toBe(1); + expect(data.rtpParameters.encodings!.length).toBe(1); expect(data.rtpParameters.encodings).toEqual( [ - { - codecPayloadType : 100, - ssrc : audioConsumer.rtpParameters.encodings?.[0].ssrc - } + expect.objectContaining( + { + codecPayloadType : 100, + ssrc : audioConsumer.rtpParameters.encodings?.[0].ssrc + }) ]); expect(data.type).toBe('simple'); expect(Array.isArray(data.consumableRtpEncodings)).toBe(true); - expect(data.consumableRtpEncodings.length).toBe(1); + expect(data.consumableRtpEncodings!.length).toBe(1); expect(data.consumableRtpEncodings).toEqual( [ - { ssrc: audioProducer.consumableRtpParameters.encodings?.[0].ssrc } + expect.objectContaining( + { ssrc: audioProducer.consumableRtpParameters.encodings?.[0].ssrc }) ]); expect(data.supportedCodecPayloadTypes).toEqual([ 100 ]); expect(data.paused).toBe(false); @@ -710,7 +728,7 @@ test('consumer.dump() succeeds', async () => { type: 'goog-remb' } ]); expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); - expect(data.rtpParameters.headerExtensions.length).toBe(4); + expect(data.rtpParameters.headerExtensions!.length).toBe(4); expect(data.rtpParameters.headerExtensions).toEqual( [ { @@ -739,7 +757,7 @@ test('consumer.dump() succeeds', async () => } ]); expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); - expect(data.rtpParameters.encodings.length).toBe(1); + expect(data.rtpParameters.encodings!.length).toBe(1); expect(data.rtpParameters.encodings).toMatchObject( [ { @@ -753,14 +771,23 @@ test('consumer.dump() succeeds', async () => } ]); expect(Array.isArray(data.consumableRtpEncodings)).toBe(true); - expect(data.consumableRtpEncodings.length).toBe(4); - expect(data.consumableRtpEncodings).toEqual( - [ - { ssrc: videoProducer.consumableRtpParameters.encodings?.[0].ssrc }, - { ssrc: videoProducer.consumableRtpParameters.encodings?.[1].ssrc }, - { ssrc: videoProducer.consumableRtpParameters.encodings?.[2].ssrc }, - { ssrc: videoProducer.consumableRtpParameters.encodings?.[3].ssrc } - ]); + expect(data.consumableRtpEncodings!.length).toBe(4); + expect(data.consumableRtpEncodings![0]).toEqual( + expect.objectContaining( + { ssrc: videoProducer.consumableRtpParameters.encodings?.[0].ssrc }) + ); + expect(data.consumableRtpEncodings![1]).toEqual( + expect.objectContaining( + { ssrc: videoProducer.consumableRtpParameters.encodings?.[1].ssrc }) + ); + expect(data.consumableRtpEncodings![2]).toEqual( + expect.objectContaining( + { ssrc: videoProducer.consumableRtpParameters.encodings?.[2].ssrc }) + ); + expect(data.consumableRtpEncodings![3]).toEqual( + expect.objectContaining( + { ssrc: videoProducer.consumableRtpParameters.encodings?.[3].ssrc }) + ); expect(data.supportedCodecPayloadTypes).toEqual([ 103 ]); expect(data.paused).toBe(true); expect(data.producerPaused).toBe(true); @@ -877,26 +904,28 @@ test('consumer.unsetPriority() succeed', async () => test('consumer.enableTraceEvent() succeed', async () => { + let dump; + await audioConsumer.enableTraceEvent([ 'rtp', 'pli' ]); - await expect(audioConsumer.dump()) - .resolves - .toMatchObject({ traceEventTypes: 'rtp,pli' }); + dump = await audioConsumer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([ 'rtp', 'pli' ])); await audioConsumer.enableTraceEvent([]); - await expect(audioConsumer.dump()) - .resolves - .toMatchObject({ traceEventTypes: '' }); + dump = await audioConsumer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([])); // @ts-ignore await audioConsumer.enableTraceEvent([ 'nack', 'FOO', 'fir' ]); - await expect(audioConsumer.dump()) - .resolves - .toMatchObject({ traceEventTypes: 'nack,fir' }); + dump = await audioConsumer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([ 'nack', 'fir' ])); await audioConsumer.enableTraceEvent(); - await expect(audioConsumer.dump()) - .resolves - .toMatchObject({ traceEventTypes: '' }); + dump = await audioConsumer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([])); }, 2000); test('consumer.enableTraceEvent() with wrong arguments rejects with TypeError', async () => @@ -946,12 +975,30 @@ test('Consumer emits "score"', async () => audioConsumer.on('score', onScore); - channel.emit(audioConsumer.id, 'score', { producer: 10, consumer: 9 }); - channel.emit(audioConsumer.id, 'score', { producer: 9, consumer: 9 }); - channel.emit(audioConsumer.id, 'score', { producer: 8, consumer: 8 }); + // Simulate a 'score' notification coming through the channel. + const builder = new flatbuffers.Builder(); + const consumerScore = new FbsConsumer.ConsumerScoreT(9, 10, [ 8 ]); + const consumerScoreNotification = new FbsConsumer.ScoreNotificationT(consumerScore); + const notificationOffset = Notification.createNotification( + builder, + builder.createString(audioConsumer.id), + Event.CONSUMER_SCORE, + NotificationBody.FBS_Consumer_ScoreNotification, + consumerScoreNotification.pack(builder) + ); + + builder.finish(notificationOffset); + + const notification = Notification.getRootAsNotification( + new flatbuffers.ByteBuffer(builder.asUint8Array())); + + channel.emit(audioConsumer.id, Event.CONSUMER_SCORE, notification); + channel.emit(audioConsumer.id, Event.CONSUMER_SCORE, notification); + channel.emit(audioConsumer.id, Event.CONSUMER_SCORE, notification); expect(onScore).toHaveBeenCalledTimes(3); - expect(audioConsumer.score).toEqual({ producer: 8, consumer: 8 }); + expect(audioConsumer.score).toEqual( + { score: 9, producerScore: 10, producerScores: [ 8 ] }); }, 2000); test('consumer.close() succeeds', async () => @@ -964,15 +1011,23 @@ test('consumer.close() succeeds', async () => expect(onObserverClose).toHaveBeenCalledTimes(1); expect(audioConsumer.closed).toBe(true); - await expect(router.dump()) - .resolves - .toMatchObject( - { - mapProducerIdConsumerIds : { [audioProducer.id]: [] }, - mapConsumerIdProducerId : {} - }); + let dump = await router.dump(); + + expect(dump.mapProducerIdConsumerIds) + .toEqual(expect.arrayContaining([ + { key: audioProducer.id, values: [ ] } + ])); + + expect(dump.mapConsumerIdProducerId) + .toEqual(expect.arrayContaining([ + { key: videoConsumer.id, value: videoProducer.id } + ])); + expect(dump.mapConsumerIdProducerId) + .toEqual(expect.arrayContaining([ + { key: videoPipeConsumer.id, value: videoProducer.id } + ])); - const dump = await transport2.dump(); + dump = await transport2.dump(); dump.consumerIds = dump.consumerIds.sort(); diff --git a/node/src/tests/test-DataConsumer.ts b/node/src/tests/test-DataConsumer.ts index 08241fcf3e..df6b829bdd 100644 --- a/node/src/tests/test-DataConsumer.ts +++ b/node/src/tests/test-DataConsumer.ts @@ -71,13 +71,17 @@ test('transport.consumeData() succeeds', async () => expect(dataConsumer1.protocol).toBe('bar'); expect(dataConsumer1.appData).toEqual({ baz: 'LOL' }); - await expect(router.dump()) - .resolves - .toMatchObject( - { - mapDataProducerIdDataConsumerIds : { [dataProducer.id]: [ dataConsumer1.id ] }, - mapDataConsumerIdDataProducerId : { [dataConsumer1.id]: dataProducer.id } - }); + const dump = await router.dump(); + + expect(dump.mapDataProducerIdDataConsumerIds) + .toEqual(expect.arrayContaining([ + { key: dataProducer.id, values: [ dataConsumer1.id ] } + ])); + + expect(dump.mapDataConsumerIdDataProducerId) + .toEqual(expect.arrayContaining([ + { key: dataConsumer1.id, value: dataProducer.id } + ])); await expect(transport2.dump()) .resolves @@ -97,11 +101,11 @@ test('dataConsumer.dump() succeeds', async () => expect(data.dataProducerId).toBe(dataConsumer1.dataProducerId); expect(data.type).toBe('sctp'); expect(typeof data.sctpStreamParameters).toBe('object'); - expect(data.sctpStreamParameters.streamId) + expect(data.sctpStreamParameters!.streamId) .toBe(dataConsumer1.sctpStreamParameters?.streamId); - expect(data.sctpStreamParameters.ordered).toBe(false); - expect(data.sctpStreamParameters.maxPacketLifeTime).toBe(4000); - expect(data.sctpStreamParameters.maxRetransmits).toBeUndefined(); + expect(data.sctpStreamParameters!.ordered).toBe(false); + expect(data.sctpStreamParameters!.maxPacketLifeTime).toBe(4000); + expect(data.sctpStreamParameters!.maxRetransmits).toBeUndefined(); expect(data.label).toBe('foo'); expect(data.protocol).toBe('bar'); }, 2000); @@ -193,13 +197,17 @@ test('dataConsumer.close() succeeds', async () => expect(onObserverClose).toHaveBeenCalledTimes(1); expect(dataConsumer1.closed).toBe(true); - await expect(router.dump()) - .resolves - .toMatchObject( - { - mapDataProducerIdDataConsumerIds : { [dataProducer.id]: [ dataConsumer2.id ] }, - mapDataConsumerIdDataProducerId : { [dataConsumer2.id]: dataProducer.id } - }); + const dump = await router.dump(); + + expect(dump.mapDataProducerIdDataConsumerIds) + .toEqual(expect.arrayContaining([ + { key: dataProducer.id, values: [ dataConsumer2.id ] } + ])); + + expect(dump.mapDataConsumerIdDataProducerId) + .toEqual(expect.arrayContaining([ + { key: dataConsumer2.id, value: dataProducer.id } + ])); await expect(transport2.dump()) .resolves diff --git a/node/src/tests/test-DataProducer.ts b/node/src/tests/test-DataProducer.ts index 711fde3d79..1b44e60cce 100644 --- a/node/src/tests/test-DataProducer.ts +++ b/node/src/tests/test-DataProducer.ts @@ -58,13 +58,14 @@ test('transport1.produceData() succeeds', async () => expect(dataProducer1.protocol).toBe('bar'); expect(dataProducer1.appData).toEqual({ foo: 1, bar: '2' }); - await expect(router.dump()) - .resolves - .toMatchObject( - { - mapDataProducerIdDataConsumerIds : { [dataProducer1.id]: [] }, - mapDataConsumerIdDataProducerId : {} - }); + const dump = await router.dump(); + + expect(dump.mapDataProducerIdDataConsumerIds) + .toEqual(expect.arrayContaining([ + { key: dataProducer1.id, values: [ ] } + ])); + + expect(dump.mapDataConsumerIdDataProducerId.length).toBe(0); await expect(transport1.dump()) .resolves @@ -108,13 +109,14 @@ test('transport2.produceData() succeeds', async () => expect(dataProducer2.protocol).toBe('bar'); expect(dataProducer2.appData).toEqual({ foo: 1, bar: '2' }); - await expect(router.dump()) - .resolves - .toMatchObject( - { - mapDataProducerIdDataConsumerIds : { [dataProducer2.id]: [] }, - mapDataConsumerIdDataProducerId : {} - }); + const dump = await router.dump(); + + expect(dump.mapDataProducerIdDataConsumerIds) + .toEqual(expect.arrayContaining([ + { key: dataProducer2.id, values: [ ] } + ])); + + expect(dump.mapDataConsumerIdDataProducerId.length).toBe(0); await expect(transport2.dump()) .resolves @@ -179,10 +181,10 @@ test('dataProducer.dump() succeeds', async () => expect(data.id).toBe(dataProducer1.id); expect(data.type).toBe('sctp'); expect(typeof data.sctpStreamParameters).toBe('object'); - expect(data.sctpStreamParameters.streamId).toBe(666); - expect(data.sctpStreamParameters.ordered).toBe(true); - expect(data.sctpStreamParameters.maxPacketLifeTime).toBeUndefined(); - expect(data.sctpStreamParameters.maxRetransmits).toBeUndefined(); + expect(data.sctpStreamParameters!.streamId).toBe(666); + expect(data.sctpStreamParameters!.ordered).toBe(true); + expect(data.sctpStreamParameters!.maxPacketLifeTime).toBeUndefined(); + expect(data.sctpStreamParameters!.maxRetransmits).toBeUndefined(); expect(data.label).toBe('foo'); expect(data.protocol).toBe('bar'); @@ -191,10 +193,10 @@ test('dataProducer.dump() succeeds', async () => expect(data.id).toBe(dataProducer2.id); expect(data.type).toBe('sctp'); expect(typeof data.sctpStreamParameters).toBe('object'); - expect(data.sctpStreamParameters.streamId).toBe(777); - expect(data.sctpStreamParameters.ordered).toBe(false); - expect(data.sctpStreamParameters.maxPacketLifeTime).toBeUndefined(); - expect(data.sctpStreamParameters.maxRetransmits).toBe(3); + expect(data.sctpStreamParameters!.streamId).toBe(777); + expect(data.sctpStreamParameters!.ordered).toBe(false); + expect(data.sctpStreamParameters!.maxPacketLifeTime).toBeUndefined(); + expect(data.sctpStreamParameters!.maxRetransmits).toBe(3); expect(data.label).toBe('foo'); expect(data.protocol).toBe('bar'); }, 2000); diff --git a/node/src/tests/test-DirectTransport.ts b/node/src/tests/test-DirectTransport.ts index 848d696ce7..a5d62c84d7 100644 --- a/node/src/tests/test-DirectTransport.ts +++ b/node/src/tests/test-DirectTransport.ts @@ -52,7 +52,7 @@ test('router.createDirectTransport() succeeds', async () => expect(data1.consumerIds).toEqual([]); expect(data1.dataProducerIds).toEqual([]); expect(data1.dataConsumerIds).toEqual([]); - expect(typeof data1.recvRtpHeaderExtensions).toBe('object'); + expect(Array.isArray(data1.recvRtpHeaderExtensions)).toBe(true); expect(typeof data1.rtpListener).toBe('object'); transport1.close(); diff --git a/node/src/tests/test-PlainTransport.ts b/node/src/tests/test-PlainTransport.ts index bfa2553d9e..bee31c73d5 100644 --- a/node/src/tests/test-PlainTransport.ts +++ b/node/src/tests/test-PlainTransport.ts @@ -109,7 +109,7 @@ test('router.createPlainTransport() succeeds', async () => expect(data1.rtcpTuple).toEqual(transport1.rtcpTuple); expect(data1.sctpParameters).toEqual(transport1.sctpParameters); expect(data1.sctpState).toBe('new'); - expect(typeof data1.recvRtpHeaderExtensions).toBe('object'); + expect(Array.isArray(data1.recvRtpHeaderExtensions)).toBe(true); expect(typeof data1.rtpListener).toBe('object'); transport1.close(); diff --git a/node/src/tests/test-Producer.ts b/node/src/tests/test-Producer.ts index 3c86e6680c..c04d6743a1 100644 --- a/node/src/tests/test-Producer.ts +++ b/node/src/tests/test-Producer.ts @@ -1,5 +1,8 @@ +import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; import { UnsupportedError } from '../errors'; +import { Notification, Body as NotificationBody, Event } from '../fbs/notification'; +import * as FbsProducer from '../fbs/producer'; const { createWorker } = mediasoup; @@ -123,8 +126,8 @@ test('transport1.produce() succeeds', async () => .resolves .toMatchObject( { - mapProducerIdConsumerIds : { [audioProducer.id]: [] }, - mapConsumerIdProducerId : {} + mapProducerIdConsumerIds : [ { key: audioProducer.id, values: [] } ], + mapConsumerIdProducerId : [] }); await expect(transport1.dump()) @@ -213,13 +216,16 @@ test('transport2.produce() succeeds', async () => expect(videoProducer.score).toEqual([]); expect(videoProducer.appData).toEqual({ foo: 1, bar: '2' }); - await expect(router.dump()) - .resolves - .toMatchObject( - { - mapProducerIdConsumerIds : { [videoProducer.id]: [] }, - mapConsumerIdProducerId : {} - }); + const dump = await router.dump(); + + expect(dump.mapProducerIdConsumerIds) + .toEqual( + expect.arrayContaining([ + { key: videoProducer.id, values: [] } + ]) + ); + + expect(dump.mapConsumerIdProducerId.length).toBe(0); await expect(transport2.dump()) .resolves @@ -520,7 +526,7 @@ test('producer.dump() succeeds', async () => }); expect(data.rtpParameters.codecs[0].rtcpFeedback).toEqual([]); expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); - expect(data.rtpParameters.headerExtensions.length).toBe(2); + expect(data.rtpParameters.headerExtensions!.length).toBe(2); expect(data.rtpParameters.headerExtensions).toEqual( [ { @@ -537,11 +543,13 @@ test('producer.dump() succeeds', async () => } ]); expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); - expect(data.rtpParameters.encodings.length).toBe(1); - expect(data.rtpParameters.encodings).toEqual( - [ - { codecPayloadType: 0 } - ]); + expect(data.rtpParameters.encodings!.length).toBe(1); + expect(data.rtpParameters.encodings![0]).toEqual( + expect.objectContaining( + { + codecPayloadType : 0 + }) + ); expect(data.type).toBe('simple'); data = await videoProducer.dump(); @@ -575,7 +583,7 @@ test('producer.dump() succeeds', async () => expect(data.rtpParameters.codecs[1].parameters).toEqual({ apt: 112 }); expect(data.rtpParameters.codecs[1].rtcpFeedback).toEqual([]); expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); - expect(data.rtpParameters.headerExtensions.length).toBe(2); + expect(data.rtpParameters.headerExtensions!.length).toBe(2); expect(data.rtpParameters.headerExtensions).toEqual( [ { @@ -592,7 +600,7 @@ test('producer.dump() succeeds', async () => } ]); expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); - expect(data.rtpParameters.encodings.length).toBe(4); + expect(data.rtpParameters.encodings!.length).toBe(4); expect(data.rtpParameters.encodings).toMatchObject( [ { @@ -638,26 +646,28 @@ test('producer.pause() and resume() succeed', async () => test('producer.enableTraceEvent() succeed', async () => { + let dump; + await audioProducer.enableTraceEvent([ 'rtp', 'pli' ]); - await expect(audioProducer.dump()) - .resolves - .toMatchObject({ traceEventTypes: 'rtp,pli' }); + dump = await audioProducer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([ 'rtp', 'pli' ])); await audioProducer.enableTraceEvent([]); - await expect(audioProducer.dump()) - .resolves - .toMatchObject({ traceEventTypes: '' }); + dump = await audioProducer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([])); // @ts-ignore await audioProducer.enableTraceEvent([ 'nack', 'FOO', 'fir' ]); - await expect(audioProducer.dump()) - .resolves - .toMatchObject({ traceEventTypes: 'nack,fir' }); + dump = await audioProducer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([ 'nack', 'fir' ])); await audioProducer.enableTraceEvent(); - await expect(audioProducer.dump()) - .resolves - .toMatchObject({ traceEventTypes: '' }); + dump = await audioProducer.dump(); + expect(dump.traceEventTypes) + .toEqual(expect.arrayContaining([])); }, 2000); test('producer.enableTraceEvent() with wrong arguments rejects with TypeError', async () => @@ -686,12 +696,32 @@ test('Producer emits "score"', async () => videoProducer.on('score', onScore); - channel.emit(videoProducer.id, 'score', [ { ssrc: 11, score: 10 } ]); - channel.emit(videoProducer.id, 'score', [ { ssrc: 11, score: 9 }, { ssrc: 22, score: 8 } ]); - channel.emit(videoProducer.id, 'score', [ { ssrc: 11, score: 9 }, { ssrc: 22, score: 9 } ]); + // Simulate a 'score' notification coming through the channel. + const builder = new flatbuffers.Builder(); + const producerScoreNotification = new FbsProducer.ScoreNotificationT([ + new FbsProducer.ScoreT(/* ssrc */ 11, /* rid */ undefined, /* score */ 10), + new FbsProducer.ScoreT(/* ssrc */ 22, /* rid */ undefined, /* score */ 9) + ]); + const notificationOffset = Notification.createNotification( + builder, + builder.createString(videoProducer.id), + Event.PRODUCER_SCORE, + NotificationBody.FBS_Producer_ScoreNotification, + producerScoreNotification.pack(builder) + ); + + builder.finish(notificationOffset); + + const notification = Notification.getRootAsNotification( + new flatbuffers.ByteBuffer(builder.asUint8Array())); + + channel.emit(videoProducer.id, Event.PRODUCER_SCORE, notification); + channel.emit(videoProducer.id, Event.PRODUCER_SCORE, notification); + channel.emit(videoProducer.id, Event.PRODUCER_SCORE, notification); expect(onScore).toHaveBeenCalledTimes(3); - expect(videoProducer.score).toEqual([ { ssrc: 11, score: 9 }, { ssrc: 22, score: 9 } ]); + expect(videoProducer.score).toEqual( + [ { ssrc: 11, score: 10 }, { ssrc: 22, score: 9 } ]); }, 2000); test('producer.close() succeeds', async () => diff --git a/node/src/tests/test-Router.ts b/node/src/tests/test-Router.ts index 9d9941f2b4..e133efbf68 100644 --- a/node/src/tests/test-Router.ts +++ b/node/src/tests/test-Router.ts @@ -74,9 +74,8 @@ test('worker.createRouter() succeeds', async () => routerIds : [ router.id ], channelMessageHandlers : { - channelRequestHandlers : [ router.id ], - payloadChannelRequestHandlers : [], - payloadChannelNotificationHandlers : [] + channelRequestHandlers : [ router.id ], + channelNotificationHandlers : [] } }); diff --git a/node/src/tests/test-WebRtcServer.ts b/node/src/tests/test-WebRtcServer.ts index ff28ebe26b..137aeb0d73 100644 --- a/node/src/tests/test-WebRtcServer.ts +++ b/node/src/tests/test-WebRtcServer.ts @@ -55,9 +55,8 @@ test('worker.createWebRtcServer() succeeds', async () => routerIds : [], channelMessageHandlers : { - channelRequestHandlers : [ webRtcServer.id ], - payloadChannelRequestHandlers : [], - payloadChannelNotificationHandlers : [] + channelRequestHandlers : [ webRtcServer.id ], + channelNotificationHandlers : [] } }); @@ -130,9 +129,8 @@ test('worker.createWebRtcServer() without specifying port succeeds', async () => routerIds : [], channelMessageHandlers : { - channelRequestHandlers : [ webRtcServer.id ], - payloadChannelRequestHandlers : [], - payloadChannelNotificationHandlers : [] + channelRequestHandlers : [ webRtcServer.id ], + channelNotificationHandlers : [] } }); @@ -568,9 +566,8 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer routerIds : [ router.id ], channelMessageHandlers : { - channelRequestHandlers : [ router.id ], - payloadChannelRequestHandlers : [], - payloadChannelNotificationHandlers : [] + channelRequestHandlers : [ router.id ], + channelNotificationHandlers : [] } }); diff --git a/node/src/tests/test-WebRtcTransport.ts b/node/src/tests/test-WebRtcTransport.ts index bc49b9a168..e5a9b4e19a 100644 --- a/node/src/tests/test-WebRtcTransport.ts +++ b/node/src/tests/test-WebRtcTransport.ts @@ -1,6 +1,10 @@ // @ts-ignore import * as pickPort from 'pick-port'; +import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; +import { Notification, Body as NotificationBody, Event } from '../fbs/notification'; +import * as FbsTransport from '../fbs/transport'; +import * as FbsWebRtcTransport from '../fbs/web-rtc-transport'; const { createWorker } = mediasoup; @@ -162,7 +166,7 @@ test('router.createWebRtcTransport() succeeds', async () => expect(data1.dtlsState).toBe(transport1.dtlsState); expect(data1.sctpParameters).toEqual(transport1.sctpParameters); expect(data1.sctpState).toBe(transport1.sctpState); - expect(typeof data1.recvRtpHeaderExtensions).toBe('object'); + expect(Array.isArray(data1.recvRtpHeaderExtensions)).toBe(true); expect(typeof data1.rtpListener).toBe('object'); transport1.close(); @@ -433,23 +437,23 @@ test('transport.enableTraceEvent() succeed', async () => await transport.enableTraceEvent([ 'foo', 'probation' ]); await expect(transport.dump()) .resolves - .toMatchObject({ traceEventTypes: 'probation' }); + .toMatchObject({ traceEventTypes: [ 'probation' ] }); await transport.enableTraceEvent([]); await expect(transport.dump()) .resolves - .toMatchObject({ traceEventTypes: '' }); + .toMatchObject({ traceEventTypes: [] }); // @ts-ignore await transport.enableTraceEvent([ 'probation', 'FOO', 'bwe', 'BAR' ]); await expect(transport.dump()) .resolves - .toMatchObject({ traceEventTypes: 'probation,bwe' }); + .toMatchObject({ traceEventTypes: [ 'probation', 'bwe' ] }); await transport.enableTraceEvent(); await expect(transport.dump()) .resolves - .toMatchObject({ traceEventTypes: '' }); + .toMatchObject({ traceEventTypes: [] }); }, 2000); test('transport.enableTraceEvent() with wrong arguments rejects with TypeError', async () => @@ -478,12 +482,32 @@ test('WebRtcTransport events succeed', async () => transport.on('icestatechange', onIceStateChange); - channel.emit(transport.id, 'icestatechange', { iceState: 'completed' }); + // Simulate a 'iceselectedtuplechange' notification coming through the channel. + const builder = new flatbuffers.Builder(); + const iceStateChangeNotification = new FbsWebRtcTransport.IceStateChangeNotificationT( + FbsWebRtcTransport.IceState.COMPLETED); + + let notificationOffset = Notification.createNotification( + builder, + builder.createString(transport.id), + Event.WEBRTCTRANSPORT_ICE_STATE_CHANGE, + NotificationBody.FBS_WebRtcTransport_IceStateChangeNotification, + iceStateChangeNotification.pack(builder) + ); + + builder.finish(notificationOffset); + + let notification = Notification.getRootAsNotification( + new flatbuffers.ByteBuffer(builder.asUint8Array())); + + channel.emit(transport.id, Event.WEBRTCTRANSPORT_ICE_STATE_CHANGE, notification); expect(onIceStateChange).toHaveBeenCalledTimes(1); expect(onIceStateChange).toHaveBeenCalledWith('completed'); expect(transport.iceState).toBe('completed'); + builder.clear(); + const onIceSelectedTuple = jest.fn(); const iceSelectedTuple = { @@ -495,28 +519,66 @@ test('WebRtcTransport events succeed', async () => }; transport.on('iceselectedtuplechange', onIceSelectedTuple); - channel.emit(transport.id, 'iceselectedtuplechange', { iceSelectedTuple }); + + // Simulate a 'icestatechange' notification coming through the channel. + const iceSelectedTupleChangeNotification = + new FbsWebRtcTransport.IceSelectedTupleChangeNotificationT( + new FbsTransport.TupleT( + iceSelectedTuple.localIp, + iceSelectedTuple.localPort, + iceSelectedTuple.remoteIp, + iceSelectedTuple.remotePort, + iceSelectedTuple.protocol) + ); + + notificationOffset = Notification.createNotification( + builder, + builder.createString(transport.id), + Event.WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE, + NotificationBody.FBS_WebRtcTransport_IceSelectedTupleChangeNotification, + iceSelectedTupleChangeNotification.pack(builder) + ); + + builder.finish(notificationOffset); + + notification = Notification.getRootAsNotification( + new flatbuffers.ByteBuffer(builder.asUint8Array())); + + channel.emit( + transport.id, Event.WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE, notification); expect(onIceSelectedTuple).toHaveBeenCalledTimes(1); expect(onIceSelectedTuple).toHaveBeenCalledWith(iceSelectedTuple); expect(transport.iceSelectedTuple).toEqual(iceSelectedTuple); + builder.clear(); + const onDtlsStateChange = jest.fn(); transport.on('dtlsstatechange', onDtlsStateChange); - channel.emit(transport.id, 'dtlsstatechange', { dtlsState: 'connecting' }); + + // Simulate a 'dtlsstatechange' notification coming through the channel. + const dtlsStateChangeNotification = new FbsWebRtcTransport.DtlsStateChangeNotificationT( + FbsWebRtcTransport.DtlsState.CONNECTING); + + notificationOffset = Notification.createNotification( + builder, + builder.createString(transport.id), + Event.WEBRTCTRANSPORT_DTLS_STATE_CHANGE, + NotificationBody.FBS_WebRtcTransport_DtlsStateChangeNotification, + dtlsStateChangeNotification.pack(builder) + ); + + builder.finish(notificationOffset); + + notification = Notification.getRootAsNotification( + new flatbuffers.ByteBuffer(builder.asUint8Array())); + + channel.emit(transport.id, Event.WEBRTCTRANSPORT_DTLS_STATE_CHANGE, notification); expect(onDtlsStateChange).toHaveBeenCalledTimes(1); expect(onDtlsStateChange).toHaveBeenCalledWith('connecting'); expect(transport.dtlsState).toBe('connecting'); - - channel.emit( - transport.id, 'dtlsstatechange', { dtlsState: 'connected', dtlsRemoteCert: 'ABCD' }); - - expect(onDtlsStateChange).toHaveBeenCalledTimes(2); - expect(onDtlsStateChange).toHaveBeenCalledWith('connected'); - expect(transport.dtlsState).toBe('connected'); - expect(transport.dtlsRemoteCert).toBe('ABCD'); }, 2000); test('WebRtcTransport methods reject if closed', async () => diff --git a/node/src/tests/test-Worker.ts b/node/src/tests/test-Worker.ts index 15ab5ace52..1840e14116 100644 --- a/node/src/tests/test-Worker.ts +++ b/node/src/tests/test-Worker.ts @@ -133,9 +133,8 @@ test('worker.dump() succeeds', async () => routerIds : [], channelMessageHandlers : { - channelRequestHandlers : [], - payloadChannelRequestHandlers : [], - payloadChannelNotificationHandlers : [] + channelRequestHandlers : [], + channelNotificationHandlers : [] } }); diff --git a/node/src/tests/test-ortc.ts b/node/src/tests/test-ortc.ts index 8dbabfb25d..b1c4d4ca16 100644 --- a/node/src/tests/test-ortc.ts +++ b/node/src/tests/test-ortc.ts @@ -338,8 +338,7 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum expect(consumableRtpParameters.rtcp).toEqual( { cname : rtpParameters.rtcp?.cname, - reducedSize : true, - mux : true + reducedSize : true }); const remoteRtpCapabilities: mediasoup.types.RtpCapabilities = @@ -504,8 +503,7 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum expect(consumerRtpParameters.rtcp).toEqual( { cname : rtpParameters.rtcp?.cname, - reducedSize : true, - mux : true + reducedSize : true }); const pipeConsumerRtpParameters = ortc.getPipeConsumerRtpParameters( @@ -551,8 +549,7 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum expect(pipeConsumerRtpParameters.rtcp).toEqual( { cname : rtpParameters.rtcp?.cname, - reducedSize : true, - mux : true + reducedSize : true }); }); diff --git a/node/src/utils.ts b/node/src/utils.ts index e91bea6604..c7821509a0 100644 --- a/node/src/utils.ts +++ b/node/src/utils.ts @@ -1,4 +1,6 @@ import { randomInt } from 'crypto'; +import { ProducerType } from './Producer'; +import { Type as FbsRtpParametersType } from './fbs/rtp-parameters'; /** * Clones the given object/array. @@ -30,3 +32,135 @@ type Only = }; export type Either = Only | Only; + +/** + * Get the flatbuffers RtpParameters type for a given Producer. + */ +export function getRtpParametersType( + producerType: ProducerType, pipe: boolean +): FbsRtpParametersType +{ + if (pipe) + { + return FbsRtpParametersType.PIPE; + } + + switch (producerType) + { + case 'simple': + return FbsRtpParametersType.SIMPLE; + + case 'simulcast': + return FbsRtpParametersType.SIMULCAST; + + case 'svc': + return FbsRtpParametersType.SVC; + + default: + return FbsRtpParametersType.NONE; + } +} + +/** + * Get the flatbuffers Producer type for a given RtpParameter type. + */ +export function getProducerType( + rtpParameterType: FbsRtpParametersType +): ProducerType +{ + switch (rtpParameterType) + { + case FbsRtpParametersType.SIMPLE: + return 'simple'; + + case FbsRtpParametersType.SIMULCAST: + return 'simulcast'; + + case FbsRtpParametersType.SVC: + return 'svc'; + + default: + throw new TypeError('invalid RtpParameter type'); + } +} + +/** + * Parse flatbuffers vector into an array of the given type. + */ +export function parseVector( + binary: any, methodName: string, parseFn?: (binary2: any) => Type +): Type[] +{ + const array: Type[] = []; + + for (let i=0; i=12.0.0" } }, + "node_modules/flatbuffers": { + "version": "23.3.3", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-23.3.3.tgz", + "integrity": "sha512-jmreOaAT1t55keaf+Z259Tvh8tR/Srry9K8dgCgvizhKSEr6gLGgaOJI2WFL5fkOpGOGRZwxUrlFn0GCmXUy6g==" + }, "node_modules/flatted": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", @@ -8192,6 +8198,11 @@ "rimraf": "^3.0.2" } }, + "flatbuffers": { + "version": "23.3.3", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-23.3.3.tgz", + "integrity": "sha512-jmreOaAT1t55keaf+Z259Tvh8tR/Srry9K8dgCgvizhKSEr6gLGgaOJI2WFL5fkOpGOGRZwxUrlFn0GCmXUy6g==" + }, "flatted": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", diff --git a/package.json b/package.json index 25ae180fd4..405ba5feb3 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "files": [ "node/lib", "worker/deps/libwebrtc", + "worker/fbs", "worker/fuzzer/include", "worker/fuzzer/src", "worker/include", @@ -57,6 +58,9 @@ "lint:node": "node npm-scripts.js lint:node", "lint:worker": "node npm-scripts.js lint:worker", "format:worker": "node npm-scripts.js format:worker", + "flatc": "npm run flatc:node && npm run flatc:worker", + "flatc:node": "node npm-scripts.js flatc:node", + "flatc:worker": "node npm-scripts.js flatc:worker", "test": "npm run test:node && npm run test:worker", "test:node": "node npm-scripts.js test:node", "test:worker": "node npm-scripts.js test:worker", @@ -86,6 +90,7 @@ }, "dependencies": { "debug": "^4.3.4", + "flatbuffers": "^23.3.3", "h264-profile-level-id": "^1.0.1", "supports-color": "^9.3.1", "uuid": "^9.0.0" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index c1042bed60..8b1755d7fe 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -35,6 +35,7 @@ hash_hasher = "2.0.3" log = "0.4.17" nohash-hasher = "0.2.0" once_cell = "1.16.0" +planus = "0.3.1" serde_json = "1.0.87" serde_repr = "0.1.9" thiserror = "1.0.37" diff --git a/rust/src/data_structures.rs b/rust/src/data_structures.rs index a27d5a5ec1..3995f530cc 100644 --- a/rust/src/data_structures.rs +++ b/rust/src/data_structures.rs @@ -791,6 +791,8 @@ impl<'a> WebRtcMessage<'a> { // | WebRTC Binary Empty | 57 | // +------------------------------------+-----------+ + /* + * TODO. pub(crate) fn new(ppid: u32, payload: Cow<'a, [u8]>) -> Result { match ppid { 51 => Ok(WebRtcMessage::String( @@ -802,6 +804,7 @@ impl<'a> WebRtcMessage<'a> { ppid => Err(ppid), } } + */ pub(crate) fn into_ppid_and_payload(self) -> (u32, Cow<'a, [u8]>) { match self { diff --git a/rust/src/fbs.rs b/rust/src/fbs.rs new file mode 100644 index 0000000000..7976abd4d4 --- /dev/null +++ b/rust/src/fbs.rs @@ -0,0 +1,45093 @@ +//! Flatbuffers data structures compiled from `.fbs` files +pub use root::fbs::*; + +const _: () = ::planus::check_version_compatibility("planus-0.3.1"); + +#[no_implicit_prelude] +mod root { + #[allow(missing_docs)] + #[allow(clippy::all)] + pub mod fbs { + pub mod active_speaker_observer { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ActiveSpeakerObserverOptions { + pub interval: u16, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for ActiveSpeakerObserverOptions { + fn default() -> Self { + Self { interval: 0 } + } + } + + impl ActiveSpeakerObserverOptions { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_interval: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_interval = field_interval.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 2>::new(builder); + + if prepared_interval.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_interval) = prepared_interval { + table_writer.write::<_, _, 2>(0, &prepared_interval); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for ActiveSpeakerObserverOptions + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for ActiveSpeakerObserverOptions + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ActiveSpeakerObserverOptions { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ActiveSpeakerObserverOptions::create(builder, &self.interval) + } + } + + #[derive(Copy, Clone)] + pub struct ActiveSpeakerObserverOptionsRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ActiveSpeakerObserverOptionsRef<'a> { + pub fn interval(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "ActiveSpeakerObserverOptions", "interval")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for ActiveSpeakerObserverOptionsRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ActiveSpeakerObserverOptionsRef"); + f.field("interval", &self.interval()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for ActiveSpeakerObserverOptions + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ActiveSpeakerObserverOptionsRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + interval: ::core::convert::TryInto::try_into(value.interval()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ActiveSpeakerObserverOptionsRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ActiveSpeakerObserverOptionsRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ActiveSpeakerObserverOptionsRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for ActiveSpeakerObserverOptions + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ActiveSpeakerObserverOptionsRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[ActiveSpeakerObserverOptionsRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct DominantSpeakerNotification { + pub producer_id: ::planus::alloc::string::String, + } + + impl DominantSpeakerNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_producer_id: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_producer_id = field_producer_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_producer_id); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for DominantSpeakerNotification + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for DominantSpeakerNotification + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for DominantSpeakerNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + DominantSpeakerNotification::create(builder, &self.producer_id) + } + } + + #[derive(Copy, Clone)] + pub struct DominantSpeakerNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DominantSpeakerNotificationRef<'a> { + pub fn producer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "DominantSpeakerNotification", "producer_id") + } + } + + impl<'a> ::core::fmt::Debug for DominantSpeakerNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DominantSpeakerNotificationRef"); + f.field("producer_id", &self.producer_id()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for DominantSpeakerNotification + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DominantSpeakerNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + producer_id: ::core::convert::TryInto::try_into(value.producer_id()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DominantSpeakerNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DominantSpeakerNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DominantSpeakerNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for DominantSpeakerNotification + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DominantSpeakerNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[DominantSpeakerNotificationRef]", + "read_as_root", + 0, + ) + }) + } + } + } + pub mod audio_level_observer { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct AudioLevelObserverOptions { + pub max_entries: u16, + pub threshold: i8, + pub interval: u16, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for AudioLevelObserverOptions { + fn default() -> Self { + Self { + max_entries: 0, + threshold: 0, + interval: 0, + } + } + } + + impl AudioLevelObserverOptions { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_max_entries: impl ::planus::WriteAsDefault, + field_threshold: impl ::planus::WriteAsDefault, + field_interval: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_max_entries = field_max_entries.prepare(builder, &0); + + let prepared_threshold = field_threshold.prepare(builder, &0); + + let prepared_interval = field_interval.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<8, 5>::new(builder); + + if prepared_max_entries.is_some() { + table_writer.calculate_size::(2); + } + if prepared_threshold.is_some() { + table_writer.calculate_size::(4); + } + if prepared_interval.is_some() { + table_writer.calculate_size::(6); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_max_entries) = + prepared_max_entries + { + table_writer.write::<_, _, 2>(0, &prepared_max_entries); + } + if let ::core::option::Option::Some(prepared_interval) = prepared_interval { + table_writer.write::<_, _, 2>(2, &prepared_interval); + } + if let ::core::option::Option::Some(prepared_threshold) = prepared_threshold + { + table_writer.write::<_, _, 1>(1, &prepared_threshold); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for AudioLevelObserverOptions { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for AudioLevelObserverOptions + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for AudioLevelObserverOptions { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + AudioLevelObserverOptions::create( + builder, + &self.max_entries, + &self.threshold, + &self.interval, + ) + } + } + + #[derive(Copy, Clone)] + pub struct AudioLevelObserverOptionsRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> AudioLevelObserverOptionsRef<'a> { + pub fn max_entries(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "AudioLevelObserverOptions", "max_entries")? + .unwrap_or(0), + ) + } + + pub fn threshold(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "AudioLevelObserverOptions", "threshold")? + .unwrap_or(0), + ) + } + + pub fn interval(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "AudioLevelObserverOptions", "interval")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for AudioLevelObserverOptionsRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("AudioLevelObserverOptionsRef"); + f.field("max_entries", &self.max_entries()); + f.field("threshold", &self.threshold()); + f.field("interval", &self.interval()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for AudioLevelObserverOptions { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: AudioLevelObserverOptionsRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + max_entries: ::core::convert::TryInto::try_into(value.max_entries()?)?, + threshold: ::core::convert::TryInto::try_into(value.threshold()?)?, + interval: ::core::convert::TryInto::try_into(value.interval()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for AudioLevelObserverOptionsRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for AudioLevelObserverOptionsRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[AudioLevelObserverOptionsRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for AudioLevelObserverOptions + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for AudioLevelObserverOptionsRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[AudioLevelObserverOptionsRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Volume { + pub producer_id: ::planus::alloc::string::String, + pub volume: i8, + } + + impl Volume { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_producer_id: impl ::planus::WriteAs<::planus::Offset>, + field_volume: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_producer_id = field_producer_id.prepare(builder); + + let prepared_volume = field_volume.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 5>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_volume.is_some() { + table_writer.calculate_size::(4); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_producer_id); + if let ::core::option::Option::Some(prepared_volume) = prepared_volume { + table_writer.write::<_, _, 1>(1, &prepared_volume); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Volume { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Volume { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Volume { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Volume::create(builder, &self.producer_id, &self.volume) + } + } + + #[derive(Copy, Clone)] + pub struct VolumeRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> VolumeRef<'a> { + pub fn producer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "Volume", "producer_id") + } + + pub fn volume(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(1, "Volume", "volume")?.unwrap_or(0)) + } + } + + impl<'a> ::core::fmt::Debug for VolumeRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("VolumeRef"); + f.field("producer_id", &self.producer_id()); + f.field("volume", &self.volume()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Volume { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: VolumeRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + producer_id: ::core::convert::TryInto::try_into(value.producer_id()?)?, + volume: ::core::convert::TryInto::try_into(value.volume()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for VolumeRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for VolumeRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[VolumeRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Volume { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for VolumeRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[VolumeRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct VolumesNotification { + pub volumes: ::planus::alloc::vec::Vec, + } + + impl VolumesNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_volumes: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_volumes = field_volumes.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer + .calculate_size::<::planus::Offset<[::planus::Offset]>>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_volumes); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for VolumesNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for VolumesNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for VolumesNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + VolumesNotification::create(builder, &self.volumes) + } + } + + #[derive(Copy, Clone)] + pub struct VolumesNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> VolumesNotificationRef<'a> { + pub fn volumes( + &self, + ) -> ::planus::Result<::planus::Vector<'a, ::planus::Result>>> + { + self.0.access_required(0, "VolumesNotification", "volumes") + } + } + + impl<'a> ::core::fmt::Debug for VolumesNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("VolumesNotificationRef"); + f.field("volumes", &self.volumes()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for VolumesNotification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: VolumesNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + volumes: value.volumes()?.to_vec_result()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for VolumesNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for VolumesNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[VolumesNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for VolumesNotification { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for VolumesNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[VolumesNotificationRef]", + "read_as_root", + 0, + ) + }) + } + } + } + pub mod common { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct StringString { + pub key: ::planus::alloc::string::String, + pub value: ::planus::alloc::string::String, + } + + impl StringString { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_key: impl ::planus::WriteAs<::planus::Offset>, + field_value: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_key = field_key.prepare(builder); + + let prepared_value = field_value.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_key); + table_writer.write::<_, _, 4>(1, &prepared_value); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for StringString { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for StringString { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for StringString { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + StringString::create(builder, &self.key, &self.value) + } + } + + #[derive(Copy, Clone)] + pub struct StringStringRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> StringStringRef<'a> { + pub fn key(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "StringString", "key") + } + + pub fn value(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "StringString", "value") + } + } + + impl<'a> ::core::fmt::Debug for StringStringRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("StringStringRef"); + f.field("key", &self.key()); + f.field("value", &self.value()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for StringString { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: StringStringRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + key: ::core::convert::TryInto::try_into(value.key()?)?, + value: ::core::convert::TryInto::try_into(value.value()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for StringStringRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for StringStringRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[StringStringRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for StringString { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for StringStringRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[StringStringRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct StringUint8 { + pub key: ::planus::alloc::string::String, + pub value: u8, + } + + impl StringUint8 { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_key: impl ::planus::WriteAs<::planus::Offset>, + field_value: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_key = field_key.prepare(builder); + + let prepared_value = field_value.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 5>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_value.is_some() { + table_writer.calculate_size::(4); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_key); + if let ::core::option::Option::Some(prepared_value) = prepared_value { + table_writer.write::<_, _, 1>(1, &prepared_value); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for StringUint8 { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for StringUint8 { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for StringUint8 { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + StringUint8::create(builder, &self.key, &self.value) + } + } + + #[derive(Copy, Clone)] + pub struct StringUint8Ref<'a>(::planus::table_reader::Table<'a>); + + impl<'a> StringUint8Ref<'a> { + pub fn key(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "StringUint8", "key") + } + + pub fn value(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(1, "StringUint8", "value")?.unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for StringUint8Ref<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("StringUint8Ref"); + f.field("key", &self.key()); + f.field("value", &self.value()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for StringUint8 { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: StringUint8Ref<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + key: ::core::convert::TryInto::try_into(value.key()?)?, + value: ::core::convert::TryInto::try_into(value.value()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for StringUint8Ref<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for StringUint8Ref<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[StringUint8Ref]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for StringUint8 { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for StringUint8Ref<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[StringUint8Ref]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Uint16String { + pub key: u16, + pub value: ::planus::alloc::string::String, + } + + impl Uint16String { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_key: impl ::planus::WriteAsDefault, + field_value: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_key = field_key.prepare(builder, &0); + + let prepared_value = field_value.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 6>::new(builder); + + if prepared_key.is_some() { + table_writer.calculate_size::(2); + } + table_writer.calculate_size::<::planus::Offset>(4); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(1, &prepared_value); + if let ::core::option::Option::Some(prepared_key) = prepared_key { + table_writer.write::<_, _, 2>(0, &prepared_key); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Uint16String { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Uint16String { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Uint16String { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + Uint16String::create(builder, &self.key, &self.value) + } + } + + #[derive(Copy, Clone)] + pub struct Uint16StringRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> Uint16StringRef<'a> { + pub fn key(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "Uint16String", "key")?.unwrap_or(0), + ) + } + + pub fn value(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "Uint16String", "value") + } + } + + impl<'a> ::core::fmt::Debug for Uint16StringRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("Uint16StringRef"); + f.field("key", &self.key()); + f.field("value", &self.value()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Uint16String { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: Uint16StringRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + key: ::core::convert::TryInto::try_into(value.key()?)?, + value: ::core::convert::TryInto::try_into(value.value()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for Uint16StringRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for Uint16StringRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[Uint16StringRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Uint16String { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for Uint16StringRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[Uint16StringRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Uint32String { + pub key: u32, + pub value: ::planus::alloc::string::String, + } + + impl Uint32String { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_key: impl ::planus::WriteAsDefault, + field_value: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_key = field_key.prepare(builder, &0); + + let prepared_value = field_value.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + if prepared_key.is_some() { + table_writer.calculate_size::(2); + } + table_writer.calculate_size::<::planus::Offset>(4); + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_key) = prepared_key { + table_writer.write::<_, _, 4>(0, &prepared_key); + } + table_writer.write::<_, _, 4>(1, &prepared_value); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Uint32String { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Uint32String { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Uint32String { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + Uint32String::create(builder, &self.key, &self.value) + } + } + + #[derive(Copy, Clone)] + pub struct Uint32StringRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> Uint32StringRef<'a> { + pub fn key(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "Uint32String", "key")?.unwrap_or(0), + ) + } + + pub fn value(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "Uint32String", "value") + } + } + + impl<'a> ::core::fmt::Debug for Uint32StringRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("Uint32StringRef"); + f.field("key", &self.key()); + f.field("value", &self.value()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Uint32String { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: Uint32StringRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + key: ::core::convert::TryInto::try_into(value.key()?)?, + value: ::core::convert::TryInto::try_into(value.value()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for Uint32StringRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for Uint32StringRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[Uint32StringRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Uint32String { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for Uint32StringRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[Uint32StringRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct StringStringArray { + pub key: ::planus::alloc::string::String, + pub values: ::core::option::Option< + ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + >, + } + + impl StringStringArray { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_key: impl ::planus::WriteAs<::planus::Offset>, + field_values: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_key = field_key.prepare(builder); + + let prepared_values = field_values.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_values.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(4); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_key); + if let ::core::option::Option::Some(prepared_values) = prepared_values { + table_writer.write::<_, _, 4>(1, &prepared_values); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for StringStringArray { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for StringStringArray { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for StringStringArray { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + StringStringArray::create(builder, &self.key, &self.values) + } + } + + #[derive(Copy, Clone)] + pub struct StringStringArrayRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> StringStringArrayRef<'a> { + pub fn key(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "StringStringArray", "key") + } + + pub fn values( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + >, + > { + self.0.access(1, "StringStringArray", "values") + } + } + + impl<'a> ::core::fmt::Debug for StringStringArrayRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("StringStringArrayRef"); + f.field("key", &self.key()); + if let ::core::option::Option::Some(field_values) = self.values().transpose() { + f.field("values", &field_values); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for StringStringArray { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: StringStringArrayRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + key: ::core::convert::TryInto::try_into(value.key()?)?, + values: if let ::core::option::Option::Some(values) = value.values()? { + ::core::option::Option::Some(values.to_vec_result()?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for StringStringArrayRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for StringStringArrayRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[StringStringArrayRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for StringStringArray { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for StringStringArrayRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[StringStringArrayRef]", "read_as_root", 0) + }) + } + } + } + pub mod consumer { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ConsumerLayers { + pub spatial_layer: i16, + pub temporal_layer: ::core::option::Option, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for ConsumerLayers { + fn default() -> Self { + Self { + spatial_layer: 0, + temporal_layer: ::core::default::Default::default(), + } + } + } + + impl ConsumerLayers { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_spatial_layer: impl ::planus::WriteAsDefault, + field_temporal_layer: impl ::planus::WriteAsOptional, + ) -> ::planus::Offset { + let prepared_spatial_layer = field_spatial_layer.prepare(builder, &0); + + let prepared_temporal_layer = field_temporal_layer.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 4>::new(builder); + + if prepared_spatial_layer.is_some() { + table_writer.calculate_size::(2); + } + if prepared_temporal_layer.is_some() { + table_writer.calculate_size::(4); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_spatial_layer) = + prepared_spatial_layer + { + table_writer.write::<_, _, 2>(0, &prepared_spatial_layer); + } + if let ::core::option::Option::Some(prepared_temporal_layer) = + prepared_temporal_layer + { + table_writer.write::<_, _, 2>(1, &prepared_temporal_layer); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ConsumerLayers { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ConsumerLayers { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ConsumerLayers { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ConsumerLayers::create(builder, &self.spatial_layer, &self.temporal_layer) + } + } + + #[derive(Copy, Clone)] + pub struct ConsumerLayersRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ConsumerLayersRef<'a> { + pub fn spatial_layer(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "ConsumerLayers", "spatial_layer")? + .unwrap_or(0), + ) + } + + pub fn temporal_layer(&self) -> ::planus::Result<::core::option::Option> { + self.0.access(1, "ConsumerLayers", "temporal_layer") + } + } + + impl<'a> ::core::fmt::Debug for ConsumerLayersRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ConsumerLayersRef"); + f.field("spatial_layer", &self.spatial_layer()); + if let ::core::option::Option::Some(field_temporal_layer) = + self.temporal_layer().transpose() + { + f.field("temporal_layer", &field_temporal_layer); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ConsumerLayers { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ConsumerLayersRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + spatial_layer: ::core::convert::TryInto::try_into(value.spatial_layer()?)?, + temporal_layer: if let ::core::option::Option::Some(temporal_layer) = + value.temporal_layer()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + temporal_layer, + )?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ConsumerLayersRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ConsumerLayersRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ConsumerLayersRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ConsumerLayers { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ConsumerLayersRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ConsumerLayersRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ConsumerScore { + pub score: u8, + pub producer_score: u8, + pub producer_scores: ::core::option::Option<::planus::alloc::vec::Vec>, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for ConsumerScore { + fn default() -> Self { + Self { + score: 0, + producer_score: 0, + producer_scores: ::core::default::Default::default(), + } + } + } + + impl ConsumerScore { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_score: impl ::planus::WriteAsDefault, + field_producer_score: impl ::planus::WriteAsDefault, + field_producer_scores: impl ::planus::WriteAsOptional<::planus::Offset<[u8]>>, + ) -> ::planus::Offset { + let prepared_score = field_score.prepare(builder, &0); + + let prepared_producer_score = field_producer_score.prepare(builder, &0); + + let prepared_producer_scores = field_producer_scores.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<8, 6>::new(builder); + + if prepared_score.is_some() { + table_writer.calculate_size::(2); + } + if prepared_producer_score.is_some() { + table_writer.calculate_size::(4); + } + if prepared_producer_scores.is_some() { + table_writer.calculate_size::<::planus::Offset<[u8]>>(6); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_producer_scores) = + prepared_producer_scores + { + table_writer.write::<_, _, 4>(2, &prepared_producer_scores); + } + if let ::core::option::Option::Some(prepared_score) = prepared_score { + table_writer.write::<_, _, 1>(0, &prepared_score); + } + if let ::core::option::Option::Some(prepared_producer_score) = + prepared_producer_score + { + table_writer.write::<_, _, 1>(1, &prepared_producer_score); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ConsumerScore { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ConsumerScore { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ConsumerScore { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ConsumerScore::create( + builder, + &self.score, + &self.producer_score, + &self.producer_scores, + ) + } + } + + #[derive(Copy, Clone)] + pub struct ConsumerScoreRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ConsumerScoreRef<'a> { + pub fn score(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "ConsumerScore", "score")?.unwrap_or(0), + ) + } + + pub fn producer_score(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "ConsumerScore", "producer_score")? + .unwrap_or(0), + ) + } + + pub fn producer_scores( + &self, + ) -> ::planus::Result<::core::option::Option<::planus::Vector<'a, u8>>> + { + self.0.access(2, "ConsumerScore", "producer_scores") + } + } + + impl<'a> ::core::fmt::Debug for ConsumerScoreRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ConsumerScoreRef"); + f.field("score", &self.score()); + f.field("producer_score", &self.producer_score()); + if let ::core::option::Option::Some(field_producer_scores) = + self.producer_scores().transpose() + { + f.field("producer_scores", &field_producer_scores); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ConsumerScore { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ConsumerScoreRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + score: ::core::convert::TryInto::try_into(value.score()?)?, + producer_score: ::core::convert::TryInto::try_into( + value.producer_score()?, + )?, + producer_scores: if let ::core::option::Option::Some(producer_scores) = + value.producer_scores()? + { + ::core::option::Option::Some(producer_scores.to_vec()?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ConsumerScoreRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ConsumerScoreRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ConsumerScoreRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ConsumerScore { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ConsumerScoreRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ConsumerScoreRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SetPreferredLayersRequest { + pub preferred_layers: ::planus::alloc::boxed::Box, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for SetPreferredLayersRequest { + fn default() -> Self { + Self { + preferred_layers: ::core::default::Default::default(), + } + } + } + + impl SetPreferredLayersRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_preferred_layers: impl ::planus::WriteAs< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_preferred_layers = field_preferred_layers.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_preferred_layers); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for SetPreferredLayersRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for SetPreferredLayersRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SetPreferredLayersRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SetPreferredLayersRequest::create(builder, &self.preferred_layers) + } + } + + #[derive(Copy, Clone)] + pub struct SetPreferredLayersRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SetPreferredLayersRequestRef<'a> { + pub fn preferred_layers(&self) -> ::planus::Result> { + self.0 + .access_required(0, "SetPreferredLayersRequest", "preferred_layers") + } + } + + impl<'a> ::core::fmt::Debug for SetPreferredLayersRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SetPreferredLayersRequestRef"); + f.field("preferred_layers", &self.preferred_layers()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for SetPreferredLayersRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SetPreferredLayersRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + preferred_layers: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.preferred_layers()?)?, + ), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SetPreferredLayersRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SetPreferredLayersRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SetPreferredLayersRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for SetPreferredLayersRequest + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SetPreferredLayersRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[SetPreferredLayersRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SetPreferredLayersResponse { + pub preferred_layers: + ::core::option::Option<::planus::alloc::boxed::Box>, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for SetPreferredLayersResponse { + fn default() -> Self { + Self { + preferred_layers: ::core::default::Default::default(), + } + } + } + + impl SetPreferredLayersResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_preferred_layers: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_preferred_layers = field_preferred_layers.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_preferred_layers.is_some() { + table_writer.calculate_size::<::planus::Offset>(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_preferred_layers) = + prepared_preferred_layers + { + table_writer.write::<_, _, 4>(0, &prepared_preferred_layers); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for SetPreferredLayersResponse + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for SetPreferredLayersResponse + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SetPreferredLayersResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SetPreferredLayersResponse::create(builder, &self.preferred_layers) + } + } + + #[derive(Copy, Clone)] + pub struct SetPreferredLayersResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SetPreferredLayersResponseRef<'a> { + pub fn preferred_layers( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0 + .access(0, "SetPreferredLayersResponse", "preferred_layers") + } + } + + impl<'a> ::core::fmt::Debug for SetPreferredLayersResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SetPreferredLayersResponseRef"); + if let ::core::option::Option::Some(field_preferred_layers) = + self.preferred_layers().transpose() + { + f.field("preferred_layers", &field_preferred_layers); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for SetPreferredLayersResponse + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SetPreferredLayersResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + preferred_layers: if let ::core::option::Option::Some(preferred_layers) = + value.preferred_layers()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(preferred_layers)?, + )) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SetPreferredLayersResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SetPreferredLayersResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SetPreferredLayersResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for SetPreferredLayersResponse + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SetPreferredLayersResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[SetPreferredLayersResponseRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SetPriorityRequest { + pub priority: u8, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for SetPriorityRequest { + fn default() -> Self { + Self { priority: 0 } + } + } + + impl SetPriorityRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_priority: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_priority = field_priority.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 1>::new(builder); + + if prepared_priority.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_priority) = prepared_priority { + table_writer.write::<_, _, 1>(0, &prepared_priority); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for SetPriorityRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for SetPriorityRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SetPriorityRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SetPriorityRequest::create(builder, &self.priority) + } + } + + #[derive(Copy, Clone)] + pub struct SetPriorityRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SetPriorityRequestRef<'a> { + pub fn priority(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "SetPriorityRequest", "priority")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for SetPriorityRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SetPriorityRequestRef"); + f.field("priority", &self.priority()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for SetPriorityRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SetPriorityRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + priority: ::core::convert::TryInto::try_into(value.priority()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SetPriorityRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SetPriorityRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SetPriorityRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for SetPriorityRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SetPriorityRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[SetPriorityRequestRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SetPriorityResponse { + pub priority: u8, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for SetPriorityResponse { + fn default() -> Self { + Self { priority: 0 } + } + } + + impl SetPriorityResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_priority: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_priority = field_priority.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 1>::new(builder); + + if prepared_priority.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_priority) = prepared_priority { + table_writer.write::<_, _, 1>(0, &prepared_priority); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for SetPriorityResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for SetPriorityResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SetPriorityResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SetPriorityResponse::create(builder, &self.priority) + } + } + + #[derive(Copy, Clone)] + pub struct SetPriorityResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SetPriorityResponseRef<'a> { + pub fn priority(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "SetPriorityResponse", "priority")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for SetPriorityResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SetPriorityResponseRef"); + f.field("priority", &self.priority()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for SetPriorityResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SetPriorityResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + priority: ::core::convert::TryInto::try_into(value.priority()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SetPriorityResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SetPriorityResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SetPriorityResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for SetPriorityResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SetPriorityResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[SetPriorityResponseRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct EnableTraceEventRequest { + pub events: ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + } + + impl EnableTraceEventRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_events: impl ::planus::WriteAs<::planus::Offset<[::planus::Offset]>>, + ) -> ::planus::Offset { + let prepared_events = field_events.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_events); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for EnableTraceEventRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for EnableTraceEventRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for EnableTraceEventRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + EnableTraceEventRequest::create(builder, &self.events) + } + } + + #[derive(Copy, Clone)] + pub struct EnableTraceEventRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> EnableTraceEventRequestRef<'a> { + pub fn events( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + > { + self.0 + .access_required(0, "EnableTraceEventRequest", "events") + } + } + + impl<'a> ::core::fmt::Debug for EnableTraceEventRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("EnableTraceEventRequestRef"); + f.field("events", &self.events()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for EnableTraceEventRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: EnableTraceEventRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + events: value.events()?.to_vec_result()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for EnableTraceEventRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for EnableTraceEventRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[EnableTraceEventRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for EnableTraceEventRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for EnableTraceEventRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[EnableTraceEventRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub enum DumpData { + SimpleConsumerDump(::planus::alloc::boxed::Box), + SimulcastConsumerDump(::planus::alloc::boxed::Box), + SvcConsumerDump(::planus::alloc::boxed::Box), + PipeConsumerDump(::planus::alloc::boxed::Box), + } + + impl DumpData { + pub fn create_simple_consumer_dump( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(1, value.prepare(builder).downcast()) + } + + pub fn create_simulcast_consumer_dump( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(2, value.prepare(builder).downcast()) + } + + pub fn create_svc_consumer_dump( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(3, value.prepare(builder).downcast()) + } + + pub fn create_pipe_consumer_dump( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(4, value.prepare(builder).downcast()) + } + } + + impl ::planus::WriteAsUnion for DumpData { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::UnionOffset { + match self { + Self::SimpleConsumerDump(value) => { + Self::create_simple_consumer_dump(builder, value) + } + Self::SimulcastConsumerDump(value) => { + Self::create_simulcast_consumer_dump(builder, value) + } + Self::SvcConsumerDump(value) => { + Self::create_svc_consumer_dump(builder, value) + } + Self::PipeConsumerDump(value) => { + Self::create_pipe_consumer_dump(builder, value) + } + } + } + } + + impl ::planus::WriteAsOptionalUnion for DumpData { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::UnionOffset> { + ::core::option::Option::Some(::planus::WriteAsUnion::prepare(self, builder)) + } + } + + #[derive(Copy, Clone, Debug)] + pub enum DumpDataRef<'a> { + SimpleConsumerDump(self::SimpleConsumerDumpRef<'a>), + SimulcastConsumerDump(self::SimulcastConsumerDumpRef<'a>), + SvcConsumerDump(self::SvcConsumerDumpRef<'a>), + PipeConsumerDump(self::PipeConsumerDumpRef<'a>), + } + + impl<'a> ::core::convert::TryFrom> for DumpData { + type Error = ::planus::Error; + + fn try_from(value: DumpDataRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(match value { + DumpDataRef::SimpleConsumerDump(value) => { + DumpData::SimpleConsumerDump(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + DumpDataRef::SimulcastConsumerDump(value) => { + DumpData::SimulcastConsumerDump(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + DumpDataRef::SvcConsumerDump(value) => { + DumpData::SvcConsumerDump(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + DumpDataRef::PipeConsumerDump(value) => { + DumpData::PipeConsumerDump(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + }) + } + } + + impl<'a> ::planus::TableReadUnion<'a> for DumpDataRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + field_offset: usize, + tag: u8, + ) -> ::core::result::Result { + match tag { + 1 => ::core::result::Result::Ok(Self::SimpleConsumerDump( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 2 => ::core::result::Result::Ok(Self::SimulcastConsumerDump( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 3 => ::core::result::Result::Ok(Self::SvcConsumerDump( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 4 => ::core::result::Result::Ok(Self::PipeConsumerDump( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + _ => ::core::result::Result::Err( + ::planus::errors::ErrorKind::UnknownUnionTag { tag }, + ), + } + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct DumpResponse { + pub data: ::core::option::Option, + pub type_: super::rtp_parameters::Type, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for DumpResponse { + fn default() -> Self { + Self { + data: ::core::default::Default::default(), + type_: super::rtp_parameters::Type::None, + } + } + } + + impl DumpResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_data: impl ::planus::WriteAsOptionalUnion, + field_type_: impl ::planus::WriteAsDefault< + super::rtp_parameters::Type, + super::rtp_parameters::Type, + >, + ) -> ::planus::Offset { + let prepared_data = field_data.prepare(builder); + + let prepared_type_ = + field_type_.prepare(builder, &super::rtp_parameters::Type::None); + + let mut table_writer = + ::planus::table_writer::TableWriter::<8, 6>::new(builder); + + if prepared_data.is_some() { + table_writer.calculate_size::(2); + table_writer.calculate_size::<::planus::Offset>(4); + } + if prepared_type_.is_some() { + table_writer.calculate_size::(6); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_data) = prepared_data { + table_writer.write::<_, _, 4>(1, &prepared_data.offset()); + } + if let ::core::option::Option::Some(prepared_data) = prepared_data { + table_writer.write::<_, _, 1>(0, &prepared_data.tag()); + } + if let ::core::option::Option::Some(prepared_type_) = prepared_type_ { + table_writer.write::<_, _, 1>(2, &prepared_type_); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for DumpResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + DumpResponse::create(builder, &self.data, &self.type_) + } + } + + #[derive(Copy, Clone)] + pub struct DumpResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DumpResponseRef<'a> { + pub fn data( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access_union(0, "DumpResponse", "data") + } + + pub fn type_(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "DumpResponse", "type_")? + .unwrap_or(super::rtp_parameters::Type::None), + ) + } + } + + impl<'a> ::core::fmt::Debug for DumpResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DumpResponseRef"); + if let ::core::option::Option::Some(field_data) = self.data().transpose() { + f.field("data", &field_data); + } + f.field("type_", &self.type_()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for DumpResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DumpResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + data: if let ::core::option::Option::Some(data) = value.data()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(data)?) + } else { + ::core::option::Option::None + }, + type_: ::core::convert::TryInto::try_into(value.type_()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DumpResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DumpResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DumpResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for DumpResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DumpResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[DumpResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct BaseConsumerDump { + pub id: ::planus::alloc::string::String, + pub producer_id: ::planus::alloc::string::String, + pub kind: super::rtp_parameters::MediaKind, + pub rtp_parameters: + ::planus::alloc::boxed::Box, + pub consumable_rtp_encodings: ::core::option::Option< + ::planus::alloc::vec::Vec, + >, + pub supported_codec_payload_types: + ::core::option::Option<::planus::alloc::vec::Vec>, + pub trace_event_types: ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + pub paused: bool, + pub producer_paused: bool, + pub priority: u8, + } + + impl BaseConsumerDump { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_id: impl ::planus::WriteAs<::planus::Offset>, + field_producer_id: impl ::planus::WriteAs<::planus::Offset>, + field_kind: impl ::planus::WriteAsDefault< + super::rtp_parameters::MediaKind, + super::rtp_parameters::MediaKind, + >, + field_rtp_parameters: impl ::planus::WriteAs< + ::planus::Offset, + >, + field_consumable_rtp_encodings: impl ::planus::WriteAsOptional< + ::planus::Offset< + [::planus::Offset], + >, + >, + field_supported_codec_payload_types: impl ::planus::WriteAsOptional< + ::planus::Offset<[u8]>, + >, + field_trace_event_types: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_paused: impl ::planus::WriteAsDefault, + field_producer_paused: impl ::planus::WriteAsDefault, + field_priority: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_id = field_id.prepare(builder); + + let prepared_producer_id = field_producer_id.prepare(builder); + + let prepared_kind = + field_kind.prepare(builder, &super::rtp_parameters::MediaKind::All); + + let prepared_rtp_parameters = field_rtp_parameters.prepare(builder); + + let prepared_consumable_rtp_encodings = + field_consumable_rtp_encodings.prepare(builder); + + let prepared_supported_codec_payload_types = + field_supported_codec_payload_types.prepare(builder); + + let prepared_trace_event_types = field_trace_event_types.prepare(builder); + + let prepared_paused = field_paused.prepare(builder, &false); + + let prepared_producer_paused = field_producer_paused.prepare(builder, &false); + + let prepared_priority = field_priority.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<22, 28>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + if prepared_kind.is_some() { + table_writer.calculate_size::(6); + } + table_writer + .calculate_size::<::planus::Offset>( + 8, + ); + if prepared_consumable_rtp_encodings.is_some() { + table_writer.calculate_size::<::planus::Offset< + [::planus::Offset], + >>(10); + } + if prepared_supported_codec_payload_types.is_some() { + table_writer.calculate_size::<::planus::Offset<[u8]>>(12); + } + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(14); + if prepared_paused.is_some() { + table_writer.calculate_size::(16); + } + if prepared_producer_paused.is_some() { + table_writer.calculate_size::(18); + } + if prepared_priority.is_some() { + table_writer.calculate_size::(20); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_id); + table_writer.write::<_, _, 4>(1, &prepared_producer_id); + table_writer.write::<_, _, 4>(3, &prepared_rtp_parameters); + if let ::core::option::Option::Some(prepared_consumable_rtp_encodings) = + prepared_consumable_rtp_encodings + { + table_writer.write::<_, _, 4>(4, &prepared_consumable_rtp_encodings); + } + if let ::core::option::Option::Some( + prepared_supported_codec_payload_types, + ) = prepared_supported_codec_payload_types + { + table_writer + .write::<_, _, 4>(5, &prepared_supported_codec_payload_types); + } + table_writer.write::<_, _, 4>(6, &prepared_trace_event_types); + if let ::core::option::Option::Some(prepared_kind) = prepared_kind { + table_writer.write::<_, _, 1>(2, &prepared_kind); + } + if let ::core::option::Option::Some(prepared_paused) = prepared_paused { + table_writer.write::<_, _, 1>(7, &prepared_paused); + } + if let ::core::option::Option::Some(prepared_producer_paused) = + prepared_producer_paused + { + table_writer.write::<_, _, 1>(8, &prepared_producer_paused); + } + if let ::core::option::Option::Some(prepared_priority) = prepared_priority { + table_writer.write::<_, _, 1>(9, &prepared_priority); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for BaseConsumerDump { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for BaseConsumerDump { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for BaseConsumerDump { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + BaseConsumerDump::create( + builder, + &self.id, + &self.producer_id, + &self.kind, + &self.rtp_parameters, + &self.consumable_rtp_encodings, + &self.supported_codec_payload_types, + &self.trace_event_types, + &self.paused, + &self.producer_paused, + &self.priority, + ) + } + } + + #[derive(Copy, Clone)] + pub struct BaseConsumerDumpRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> BaseConsumerDumpRef<'a> { + pub fn id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "BaseConsumerDump", "id") + } + + pub fn producer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "BaseConsumerDump", "producer_id") + } + + pub fn kind(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "BaseConsumerDump", "kind")? + .unwrap_or(super::rtp_parameters::MediaKind::All), + ) + } + + pub fn rtp_parameters( + &self, + ) -> ::planus::Result> { + self.0 + .access_required(3, "BaseConsumerDump", "rtp_parameters") + } + + pub fn consumable_rtp_encodings( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector< + 'a, + ::planus::Result>, + >, + >, + > { + self.0 + .access(4, "BaseConsumerDump", "consumable_rtp_encodings") + } + + pub fn supported_codec_payload_types( + &self, + ) -> ::planus::Result<::core::option::Option<::planus::Vector<'a, u8>>> + { + self.0 + .access(5, "BaseConsumerDump", "supported_codec_payload_types") + } + + pub fn trace_event_types( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + > { + self.0 + .access_required(6, "BaseConsumerDump", "trace_event_types") + } + + pub fn paused(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(7, "BaseConsumerDump", "paused")? + .unwrap_or(false), + ) + } + + pub fn producer_paused(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(8, "BaseConsumerDump", "producer_paused")? + .unwrap_or(false), + ) + } + + pub fn priority(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(9, "BaseConsumerDump", "priority")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for BaseConsumerDumpRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("BaseConsumerDumpRef"); + f.field("id", &self.id()); + f.field("producer_id", &self.producer_id()); + f.field("kind", &self.kind()); + f.field("rtp_parameters", &self.rtp_parameters()); + if let ::core::option::Option::Some(field_consumable_rtp_encodings) = + self.consumable_rtp_encodings().transpose() + { + f.field("consumable_rtp_encodings", &field_consumable_rtp_encodings); + } + if let ::core::option::Option::Some(field_supported_codec_payload_types) = + self.supported_codec_payload_types().transpose() + { + f.field( + "supported_codec_payload_types", + &field_supported_codec_payload_types, + ); + } + f.field("trace_event_types", &self.trace_event_types()); + f.field("paused", &self.paused()); + f.field("producer_paused", &self.producer_paused()); + f.field("priority", &self.priority()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for BaseConsumerDump { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: BaseConsumerDumpRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + id: ::core::convert::TryInto::try_into(value.id()?)?, + producer_id: ::core::convert::TryInto::try_into(value.producer_id()?)?, + kind: ::core::convert::TryInto::try_into(value.kind()?)?, + rtp_parameters: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.rtp_parameters()?)?, + ), + consumable_rtp_encodings: if let ::core::option::Option::Some( + consumable_rtp_encodings, + ) = value.consumable_rtp_encodings()? + { + ::core::option::Option::Some(consumable_rtp_encodings.to_vec_result()?) + } else { + ::core::option::Option::None + }, + supported_codec_payload_types: if let ::core::option::Option::Some( + supported_codec_payload_types, + ) = + value.supported_codec_payload_types()? + { + ::core::option::Option::Some(supported_codec_payload_types.to_vec()?) + } else { + ::core::option::Option::None + }, + trace_event_types: value.trace_event_types()?.to_vec_result()?, + paused: ::core::convert::TryInto::try_into(value.paused()?)?, + producer_paused: ::core::convert::TryInto::try_into( + value.producer_paused()?, + )?, + priority: ::core::convert::TryInto::try_into(value.priority()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for BaseConsumerDumpRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for BaseConsumerDumpRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[BaseConsumerDumpRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for BaseConsumerDump { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for BaseConsumerDumpRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[BaseConsumerDumpRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct SimpleConsumerDump { + pub base: ::planus::alloc::boxed::Box, + pub rtp_stream: ::planus::alloc::boxed::Box, + } + + impl SimpleConsumerDump { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + field_rtp_stream: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let prepared_rtp_stream = field_rtp_stream.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_base); + table_writer.write::<_, _, 4>(1, &prepared_rtp_stream); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for SimpleConsumerDump { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for SimpleConsumerDump { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SimpleConsumerDump { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SimpleConsumerDump::create(builder, &self.base, &self.rtp_stream) + } + } + + #[derive(Copy, Clone)] + pub struct SimpleConsumerDumpRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SimpleConsumerDumpRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "SimpleConsumerDump", "base") + } + + pub fn rtp_stream(&self) -> ::planus::Result> { + self.0 + .access_required(1, "SimpleConsumerDump", "rtp_stream") + } + } + + impl<'a> ::core::fmt::Debug for SimpleConsumerDumpRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SimpleConsumerDumpRef"); + f.field("base", &self.base()); + f.field("rtp_stream", &self.rtp_stream()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for SimpleConsumerDump { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SimpleConsumerDumpRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + rtp_stream: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.rtp_stream()?)?, + ), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SimpleConsumerDumpRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SimpleConsumerDumpRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SimpleConsumerDumpRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for SimpleConsumerDump { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SimpleConsumerDumpRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[SimpleConsumerDumpRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct SimulcastConsumerDump { + pub base: ::planus::alloc::boxed::Box, + pub rtp_stream: ::planus::alloc::boxed::Box, + pub preferred_spatial_layer: i16, + pub target_spatial_layer: i16, + pub current_spatial_layer: i16, + pub preferred_temporal_layer: i16, + pub target_temporal_layer: i16, + pub current_temporal_layer: i16, + } + + impl SimulcastConsumerDump { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + field_rtp_stream: impl ::planus::WriteAs<::planus::Offset>, + field_preferred_spatial_layer: impl ::planus::WriteAsDefault, + field_target_spatial_layer: impl ::planus::WriteAsDefault, + field_current_spatial_layer: impl ::planus::WriteAsDefault, + field_preferred_temporal_layer: impl ::planus::WriteAsDefault, + field_target_temporal_layer: impl ::planus::WriteAsDefault, + field_current_temporal_layer: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let prepared_rtp_stream = field_rtp_stream.prepare(builder); + + let prepared_preferred_spatial_layer = + field_preferred_spatial_layer.prepare(builder, &0); + + let prepared_target_spatial_layer = + field_target_spatial_layer.prepare(builder, &0); + + let prepared_current_spatial_layer = + field_current_spatial_layer.prepare(builder, &0); + + let prepared_preferred_temporal_layer = + field_preferred_temporal_layer.prepare(builder, &0); + + let prepared_target_temporal_layer = + field_target_temporal_layer.prepare(builder, &0); + + let prepared_current_temporal_layer = + field_current_temporal_layer.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<18, 20>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + if prepared_preferred_spatial_layer.is_some() { + table_writer.calculate_size::(6); + } + if prepared_target_spatial_layer.is_some() { + table_writer.calculate_size::(8); + } + if prepared_current_spatial_layer.is_some() { + table_writer.calculate_size::(10); + } + if prepared_preferred_temporal_layer.is_some() { + table_writer.calculate_size::(12); + } + if prepared_target_temporal_layer.is_some() { + table_writer.calculate_size::(14); + } + if prepared_current_temporal_layer.is_some() { + table_writer.calculate_size::(16); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_base); + table_writer.write::<_, _, 4>(1, &prepared_rtp_stream); + if let ::core::option::Option::Some(prepared_preferred_spatial_layer) = + prepared_preferred_spatial_layer + { + table_writer.write::<_, _, 2>(2, &prepared_preferred_spatial_layer); + } + if let ::core::option::Option::Some(prepared_target_spatial_layer) = + prepared_target_spatial_layer + { + table_writer.write::<_, _, 2>(3, &prepared_target_spatial_layer); + } + if let ::core::option::Option::Some(prepared_current_spatial_layer) = + prepared_current_spatial_layer + { + table_writer.write::<_, _, 2>(4, &prepared_current_spatial_layer); + } + if let ::core::option::Option::Some(prepared_preferred_temporal_layer) = + prepared_preferred_temporal_layer + { + table_writer.write::<_, _, 2>(5, &prepared_preferred_temporal_layer); + } + if let ::core::option::Option::Some(prepared_target_temporal_layer) = + prepared_target_temporal_layer + { + table_writer.write::<_, _, 2>(6, &prepared_target_temporal_layer); + } + if let ::core::option::Option::Some(prepared_current_temporal_layer) = + prepared_current_temporal_layer + { + table_writer.write::<_, _, 2>(7, &prepared_current_temporal_layer); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for SimulcastConsumerDump { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for SimulcastConsumerDump { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SimulcastConsumerDump { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SimulcastConsumerDump::create( + builder, + &self.base, + &self.rtp_stream, + &self.preferred_spatial_layer, + &self.target_spatial_layer, + &self.current_spatial_layer, + &self.preferred_temporal_layer, + &self.target_temporal_layer, + &self.current_temporal_layer, + ) + } + } + + #[derive(Copy, Clone)] + pub struct SimulcastConsumerDumpRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SimulcastConsumerDumpRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "SimulcastConsumerDump", "base") + } + + pub fn rtp_stream(&self) -> ::planus::Result> { + self.0 + .access_required(1, "SimulcastConsumerDump", "rtp_stream") + } + + pub fn preferred_spatial_layer(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "SimulcastConsumerDump", "preferred_spatial_layer")? + .unwrap_or(0), + ) + } + + pub fn target_spatial_layer(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(3, "SimulcastConsumerDump", "target_spatial_layer")? + .unwrap_or(0), + ) + } + + pub fn current_spatial_layer(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(4, "SimulcastConsumerDump", "current_spatial_layer")? + .unwrap_or(0), + ) + } + + pub fn preferred_temporal_layer(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(5, "SimulcastConsumerDump", "preferred_temporal_layer")? + .unwrap_or(0), + ) + } + + pub fn target_temporal_layer(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(6, "SimulcastConsumerDump", "target_temporal_layer")? + .unwrap_or(0), + ) + } + + pub fn current_temporal_layer(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(7, "SimulcastConsumerDump", "current_temporal_layer")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for SimulcastConsumerDumpRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SimulcastConsumerDumpRef"); + f.field("base", &self.base()); + f.field("rtp_stream", &self.rtp_stream()); + f.field("preferred_spatial_layer", &self.preferred_spatial_layer()); + f.field("target_spatial_layer", &self.target_spatial_layer()); + f.field("current_spatial_layer", &self.current_spatial_layer()); + f.field("preferred_temporal_layer", &self.preferred_temporal_layer()); + f.field("target_temporal_layer", &self.target_temporal_layer()); + f.field("current_temporal_layer", &self.current_temporal_layer()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for SimulcastConsumerDump { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SimulcastConsumerDumpRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + rtp_stream: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.rtp_stream()?)?, + ), + preferred_spatial_layer: ::core::convert::TryInto::try_into( + value.preferred_spatial_layer()?, + )?, + target_spatial_layer: ::core::convert::TryInto::try_into( + value.target_spatial_layer()?, + )?, + current_spatial_layer: ::core::convert::TryInto::try_into( + value.current_spatial_layer()?, + )?, + preferred_temporal_layer: ::core::convert::TryInto::try_into( + value.preferred_temporal_layer()?, + )?, + target_temporal_layer: ::core::convert::TryInto::try_into( + value.target_temporal_layer()?, + )?, + current_temporal_layer: ::core::convert::TryInto::try_into( + value.current_temporal_layer()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SimulcastConsumerDumpRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SimulcastConsumerDumpRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SimulcastConsumerDumpRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for SimulcastConsumerDump { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SimulcastConsumerDumpRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[SimulcastConsumerDumpRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct SvcConsumerDump { + pub base: ::planus::alloc::boxed::Box, + pub rtp_stream: ::planus::alloc::boxed::Box, + pub preferred_spatial_layer: i16, + pub target_spatial_layer: i16, + pub current_spatial_layer: i16, + pub preferred_temporal_layer: i16, + pub target_temporal_layer: i16, + pub current_temporal_layer: i16, + } + + impl SvcConsumerDump { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + field_rtp_stream: impl ::planus::WriteAs<::planus::Offset>, + field_preferred_spatial_layer: impl ::planus::WriteAsDefault, + field_target_spatial_layer: impl ::planus::WriteAsDefault, + field_current_spatial_layer: impl ::planus::WriteAsDefault, + field_preferred_temporal_layer: impl ::planus::WriteAsDefault, + field_target_temporal_layer: impl ::planus::WriteAsDefault, + field_current_temporal_layer: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let prepared_rtp_stream = field_rtp_stream.prepare(builder); + + let prepared_preferred_spatial_layer = + field_preferred_spatial_layer.prepare(builder, &0); + + let prepared_target_spatial_layer = + field_target_spatial_layer.prepare(builder, &0); + + let prepared_current_spatial_layer = + field_current_spatial_layer.prepare(builder, &0); + + let prepared_preferred_temporal_layer = + field_preferred_temporal_layer.prepare(builder, &0); + + let prepared_target_temporal_layer = + field_target_temporal_layer.prepare(builder, &0); + + let prepared_current_temporal_layer = + field_current_temporal_layer.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<18, 20>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + if prepared_preferred_spatial_layer.is_some() { + table_writer.calculate_size::(6); + } + if prepared_target_spatial_layer.is_some() { + table_writer.calculate_size::(8); + } + if prepared_current_spatial_layer.is_some() { + table_writer.calculate_size::(10); + } + if prepared_preferred_temporal_layer.is_some() { + table_writer.calculate_size::(12); + } + if prepared_target_temporal_layer.is_some() { + table_writer.calculate_size::(14); + } + if prepared_current_temporal_layer.is_some() { + table_writer.calculate_size::(16); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_base); + table_writer.write::<_, _, 4>(1, &prepared_rtp_stream); + if let ::core::option::Option::Some(prepared_preferred_spatial_layer) = + prepared_preferred_spatial_layer + { + table_writer.write::<_, _, 2>(2, &prepared_preferred_spatial_layer); + } + if let ::core::option::Option::Some(prepared_target_spatial_layer) = + prepared_target_spatial_layer + { + table_writer.write::<_, _, 2>(3, &prepared_target_spatial_layer); + } + if let ::core::option::Option::Some(prepared_current_spatial_layer) = + prepared_current_spatial_layer + { + table_writer.write::<_, _, 2>(4, &prepared_current_spatial_layer); + } + if let ::core::option::Option::Some(prepared_preferred_temporal_layer) = + prepared_preferred_temporal_layer + { + table_writer.write::<_, _, 2>(5, &prepared_preferred_temporal_layer); + } + if let ::core::option::Option::Some(prepared_target_temporal_layer) = + prepared_target_temporal_layer + { + table_writer.write::<_, _, 2>(6, &prepared_target_temporal_layer); + } + if let ::core::option::Option::Some(prepared_current_temporal_layer) = + prepared_current_temporal_layer + { + table_writer.write::<_, _, 2>(7, &prepared_current_temporal_layer); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for SvcConsumerDump { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for SvcConsumerDump { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SvcConsumerDump { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SvcConsumerDump::create( + builder, + &self.base, + &self.rtp_stream, + &self.preferred_spatial_layer, + &self.target_spatial_layer, + &self.current_spatial_layer, + &self.preferred_temporal_layer, + &self.target_temporal_layer, + &self.current_temporal_layer, + ) + } + } + + #[derive(Copy, Clone)] + pub struct SvcConsumerDumpRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SvcConsumerDumpRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "SvcConsumerDump", "base") + } + + pub fn rtp_stream(&self) -> ::planus::Result> { + self.0.access_required(1, "SvcConsumerDump", "rtp_stream") + } + + pub fn preferred_spatial_layer(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "SvcConsumerDump", "preferred_spatial_layer")? + .unwrap_or(0), + ) + } + + pub fn target_spatial_layer(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(3, "SvcConsumerDump", "target_spatial_layer")? + .unwrap_or(0), + ) + } + + pub fn current_spatial_layer(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(4, "SvcConsumerDump", "current_spatial_layer")? + .unwrap_or(0), + ) + } + + pub fn preferred_temporal_layer(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(5, "SvcConsumerDump", "preferred_temporal_layer")? + .unwrap_or(0), + ) + } + + pub fn target_temporal_layer(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(6, "SvcConsumerDump", "target_temporal_layer")? + .unwrap_or(0), + ) + } + + pub fn current_temporal_layer(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(7, "SvcConsumerDump", "current_temporal_layer")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for SvcConsumerDumpRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SvcConsumerDumpRef"); + f.field("base", &self.base()); + f.field("rtp_stream", &self.rtp_stream()); + f.field("preferred_spatial_layer", &self.preferred_spatial_layer()); + f.field("target_spatial_layer", &self.target_spatial_layer()); + f.field("current_spatial_layer", &self.current_spatial_layer()); + f.field("preferred_temporal_layer", &self.preferred_temporal_layer()); + f.field("target_temporal_layer", &self.target_temporal_layer()); + f.field("current_temporal_layer", &self.current_temporal_layer()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for SvcConsumerDump { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SvcConsumerDumpRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + rtp_stream: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.rtp_stream()?)?, + ), + preferred_spatial_layer: ::core::convert::TryInto::try_into( + value.preferred_spatial_layer()?, + )?, + target_spatial_layer: ::core::convert::TryInto::try_into( + value.target_spatial_layer()?, + )?, + current_spatial_layer: ::core::convert::TryInto::try_into( + value.current_spatial_layer()?, + )?, + preferred_temporal_layer: ::core::convert::TryInto::try_into( + value.preferred_temporal_layer()?, + )?, + target_temporal_layer: ::core::convert::TryInto::try_into( + value.target_temporal_layer()?, + )?, + current_temporal_layer: ::core::convert::TryInto::try_into( + value.current_temporal_layer()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SvcConsumerDumpRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SvcConsumerDumpRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SvcConsumerDumpRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for SvcConsumerDump { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SvcConsumerDumpRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[SvcConsumerDumpRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct PipeConsumerDump { + pub base: ::planus::alloc::boxed::Box, + pub rtp_streams: ::planus::alloc::vec::Vec, + } + + impl PipeConsumerDump { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + field_rtp_streams: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let prepared_rtp_streams = field_rtp_streams.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(4); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_base); + table_writer.write::<_, _, 4>(1, &prepared_rtp_streams); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for PipeConsumerDump { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for PipeConsumerDump { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for PipeConsumerDump { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + PipeConsumerDump::create(builder, &self.base, &self.rtp_streams) + } + } + + #[derive(Copy, Clone)] + pub struct PipeConsumerDumpRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> PipeConsumerDumpRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "PipeConsumerDump", "base") + } + + pub fn rtp_streams( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result>>, + > { + self.0.access_required(1, "PipeConsumerDump", "rtp_streams") + } + } + + impl<'a> ::core::fmt::Debug for PipeConsumerDumpRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("PipeConsumerDumpRef"); + f.field("base", &self.base()); + f.field("rtp_streams", &self.rtp_streams()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for PipeConsumerDump { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: PipeConsumerDumpRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + rtp_streams: value.rtp_streams()?.to_vec_result()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for PipeConsumerDumpRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for PipeConsumerDumpRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[PipeConsumerDumpRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for PipeConsumerDump { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for PipeConsumerDumpRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[PipeConsumerDumpRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct GetStatsResponse { + pub stats: + ::core::option::Option<::planus::alloc::vec::Vec>, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for GetStatsResponse { + fn default() -> Self { + Self { + stats: ::core::default::Default::default(), + } + } + } + + impl GetStatsResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_stats: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_stats = field_stats.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_stats.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_stats) = prepared_stats { + table_writer.write::<_, _, 4>(0, &prepared_stats); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for GetStatsResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + GetStatsResponse::create(builder, &self.stats) + } + } + + #[derive(Copy, Clone)] + pub struct GetStatsResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> GetStatsResponseRef<'a> { + pub fn stats( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result>>, + >, + > { + self.0.access(0, "GetStatsResponse", "stats") + } + } + + impl<'a> ::core::fmt::Debug for GetStatsResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("GetStatsResponseRef"); + if let ::core::option::Option::Some(field_stats) = self.stats().transpose() { + f.field("stats", &field_stats); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for GetStatsResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: GetStatsResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + stats: if let ::core::option::Option::Some(stats) = value.stats()? { + ::core::option::Option::Some(stats.to_vec_result()?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for GetStatsResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for GetStatsResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[GetStatsResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for GetStatsResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for GetStatsResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[GetStatsResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct LayersChangeNotification { + pub layers: + ::core::option::Option<::planus::alloc::boxed::Box>, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for LayersChangeNotification { + fn default() -> Self { + Self { + layers: ::core::default::Default::default(), + } + } + } + + impl LayersChangeNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_layers: impl ::planus::WriteAsOptional<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_layers = field_layers.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_layers.is_some() { + table_writer.calculate_size::<::planus::Offset>(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_layers) = prepared_layers { + table_writer.write::<_, _, 4>(0, &prepared_layers); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for LayersChangeNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for LayersChangeNotification + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for LayersChangeNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + LayersChangeNotification::create(builder, &self.layers) + } + } + + #[derive(Copy, Clone)] + pub struct LayersChangeNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> LayersChangeNotificationRef<'a> { + pub fn layers( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(0, "LayersChangeNotification", "layers") + } + } + + impl<'a> ::core::fmt::Debug for LayersChangeNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("LayersChangeNotificationRef"); + if let ::core::option::Option::Some(field_layers) = self.layers().transpose() { + f.field("layers", &field_layers); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for LayersChangeNotification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: LayersChangeNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + layers: if let ::core::option::Option::Some(layers) = value.layers()? { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(layers)?, + )) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for LayersChangeNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for LayersChangeNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[LayersChangeNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for LayersChangeNotification + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for LayersChangeNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[LayersChangeNotificationRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct RtpNotification { + pub data: ::planus::alloc::vec::Vec, + } + + impl RtpNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_data: impl ::planus::WriteAs<::planus::Offset<[u8]>>, + ) -> ::planus::Offset { + let prepared_data = field_data.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset<[u8]>>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_data); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RtpNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RtpNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RtpNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + RtpNotification::create(builder, &self.data) + } + } + + #[derive(Copy, Clone)] + pub struct RtpNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RtpNotificationRef<'a> { + pub fn data(&self) -> ::planus::Result<::planus::Vector<'a, u8>> { + self.0.access_required(0, "RtpNotification", "data") + } + } + + impl<'a> ::core::fmt::Debug for RtpNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RtpNotificationRef"); + f.field("data", &self.data()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RtpNotification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RtpNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + data: value.data()?.to_vec()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RtpNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RtpNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RtpNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RtpNotification { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RtpNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[RtpNotificationRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ScoreNotification { + pub score: ::planus::alloc::boxed::Box, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for ScoreNotification { + fn default() -> Self { + Self { + score: ::core::default::Default::default(), + } + } + } + + impl ScoreNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_score: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_score = field_score.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_score); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ScoreNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ScoreNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ScoreNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ScoreNotification::create(builder, &self.score) + } + } + + #[derive(Copy, Clone)] + pub struct ScoreNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ScoreNotificationRef<'a> { + pub fn score(&self) -> ::planus::Result> { + self.0.access_required(0, "ScoreNotification", "score") + } + } + + impl<'a> ::core::fmt::Debug for ScoreNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ScoreNotificationRef"); + f.field("score", &self.score()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ScoreNotification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ScoreNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + score: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.score()?)?, + ), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ScoreNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ScoreNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ScoreNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ScoreNotification { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ScoreNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ScoreNotificationRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum TraceType { + Keyframe = 0, + Fir = 1, + Nack = 2, + Pli = 3, + Rtp = 4, + } + + impl ::core::convert::TryFrom for TraceType { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 0 => ::core::result::Result::Ok(TraceType::Keyframe), + 1 => ::core::result::Result::Ok(TraceType::Fir), + 2 => ::core::result::Result::Ok(TraceType::Nack), + 3 => ::core::result::Result::Ok(TraceType::Pli), + 4 => ::core::result::Result::Ok(TraceType::Rtp), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: TraceType) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for TraceType { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for TraceType { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for TraceType { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> TraceType { + *self + } + } + + impl ::planus::WriteAsDefault for TraceType { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &TraceType, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for TraceType { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for TraceType { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for TraceType { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "TraceType", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for TraceType { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum TraceDirection { + DirectionIn = 0, + DirectionOut = 1, + } + + impl ::core::convert::TryFrom for TraceDirection { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 0 => ::core::result::Result::Ok(TraceDirection::DirectionIn), + 1 => ::core::result::Result::Ok(TraceDirection::DirectionOut), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: TraceDirection) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for TraceDirection { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for TraceDirection { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for TraceDirection { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> TraceDirection { + *self + } + } + + impl ::planus::WriteAsDefault for TraceDirection { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &TraceDirection, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for TraceDirection { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for TraceDirection { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for TraceDirection { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "TraceDirection", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for TraceDirection { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub enum TraceInfo { + KeyFrameTraceInfo(::planus::alloc::boxed::Box), + FirTraceInfo(::planus::alloc::boxed::Box), + PliTraceInfo(::planus::alloc::boxed::Box), + RtpTraceInfo(::planus::alloc::boxed::Box), + } + + impl TraceInfo { + pub fn create_key_frame_trace_info( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(1, value.prepare(builder).downcast()) + } + + pub fn create_fir_trace_info( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(2, value.prepare(builder).downcast()) + } + + pub fn create_pli_trace_info( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(3, value.prepare(builder).downcast()) + } + + pub fn create_rtp_trace_info( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(4, value.prepare(builder).downcast()) + } + } + + impl ::planus::WriteAsUnion for TraceInfo { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::UnionOffset { + match self { + Self::KeyFrameTraceInfo(value) => { + Self::create_key_frame_trace_info(builder, value) + } + Self::FirTraceInfo(value) => Self::create_fir_trace_info(builder, value), + Self::PliTraceInfo(value) => Self::create_pli_trace_info(builder, value), + Self::RtpTraceInfo(value) => Self::create_rtp_trace_info(builder, value), + } + } + } + + impl ::planus::WriteAsOptionalUnion for TraceInfo { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::UnionOffset> { + ::core::option::Option::Some(::planus::WriteAsUnion::prepare(self, builder)) + } + } + + #[derive(Copy, Clone, Debug)] + pub enum TraceInfoRef<'a> { + KeyFrameTraceInfo(self::KeyFrameTraceInfoRef<'a>), + FirTraceInfo(self::FirTraceInfoRef<'a>), + PliTraceInfo(self::PliTraceInfoRef<'a>), + RtpTraceInfo(self::RtpTraceInfoRef<'a>), + } + + impl<'a> ::core::convert::TryFrom> for TraceInfo { + type Error = ::planus::Error; + + fn try_from(value: TraceInfoRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(match value { + TraceInfoRef::KeyFrameTraceInfo(value) => { + TraceInfo::KeyFrameTraceInfo(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + TraceInfoRef::FirTraceInfo(value) => { + TraceInfo::FirTraceInfo(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + TraceInfoRef::PliTraceInfo(value) => { + TraceInfo::PliTraceInfo(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + TraceInfoRef::RtpTraceInfo(value) => { + TraceInfo::RtpTraceInfo(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + }) + } + } + + impl<'a> ::planus::TableReadUnion<'a> for TraceInfoRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + field_offset: usize, + tag: u8, + ) -> ::core::result::Result { + match tag { + 1 => ::core::result::Result::Ok(Self::KeyFrameTraceInfo( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 2 => ::core::result::Result::Ok(Self::FirTraceInfo( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 3 => ::core::result::Result::Ok(Self::PliTraceInfo( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 4 => ::core::result::Result::Ok(Self::RtpTraceInfo( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + _ => ::core::result::Result::Err( + ::planus::errors::ErrorKind::UnknownUnionTag { tag }, + ), + } + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct KeyFrameTraceInfo { + pub is_rtx: bool, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for KeyFrameTraceInfo { + fn default() -> Self { + Self { is_rtx: false } + } + } + + impl KeyFrameTraceInfo { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_is_rtx: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_is_rtx = field_is_rtx.prepare(builder, &false); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 1>::new(builder); + + if prepared_is_rtx.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_is_rtx) = prepared_is_rtx { + table_writer.write::<_, _, 1>(0, &prepared_is_rtx); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for KeyFrameTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for KeyFrameTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for KeyFrameTraceInfo { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + KeyFrameTraceInfo::create(builder, &self.is_rtx) + } + } + + #[derive(Copy, Clone)] + pub struct KeyFrameTraceInfoRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> KeyFrameTraceInfoRef<'a> { + pub fn is_rtx(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "KeyFrameTraceInfo", "is_rtx")? + .unwrap_or(false), + ) + } + } + + impl<'a> ::core::fmt::Debug for KeyFrameTraceInfoRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("KeyFrameTraceInfoRef"); + f.field("is_rtx", &self.is_rtx()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for KeyFrameTraceInfo { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: KeyFrameTraceInfoRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + is_rtx: ::core::convert::TryInto::try_into(value.is_rtx()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for KeyFrameTraceInfoRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for KeyFrameTraceInfoRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[KeyFrameTraceInfoRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for KeyFrameTraceInfo { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for KeyFrameTraceInfoRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[KeyFrameTraceInfoRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct FirTraceInfo { + pub ssrc: u32, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for FirTraceInfo { + fn default() -> Self { + Self { ssrc: 0 } + } + } + + impl FirTraceInfo { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ssrc: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_ssrc = field_ssrc.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_ssrc.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_ssrc) = prepared_ssrc { + table_writer.write::<_, _, 4>(0, &prepared_ssrc); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for FirTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for FirTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for FirTraceInfo { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + FirTraceInfo::create(builder, &self.ssrc) + } + } + + #[derive(Copy, Clone)] + pub struct FirTraceInfoRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> FirTraceInfoRef<'a> { + pub fn ssrc(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "FirTraceInfo", "ssrc")?.unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for FirTraceInfoRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("FirTraceInfoRef"); + f.field("ssrc", &self.ssrc()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for FirTraceInfo { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: FirTraceInfoRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ssrc: ::core::convert::TryInto::try_into(value.ssrc()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for FirTraceInfoRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for FirTraceInfoRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[FirTraceInfoRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for FirTraceInfo { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for FirTraceInfoRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[FirTraceInfoRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct PliTraceInfo { + pub ssrc: u32, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for PliTraceInfo { + fn default() -> Self { + Self { ssrc: 0 } + } + } + + impl PliTraceInfo { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ssrc: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_ssrc = field_ssrc.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_ssrc.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_ssrc) = prepared_ssrc { + table_writer.write::<_, _, 4>(0, &prepared_ssrc); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for PliTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for PliTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for PliTraceInfo { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + PliTraceInfo::create(builder, &self.ssrc) + } + } + + #[derive(Copy, Clone)] + pub struct PliTraceInfoRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> PliTraceInfoRef<'a> { + pub fn ssrc(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "PliTraceInfo", "ssrc")?.unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for PliTraceInfoRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("PliTraceInfoRef"); + f.field("ssrc", &self.ssrc()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for PliTraceInfo { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: PliTraceInfoRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ssrc: ::core::convert::TryInto::try_into(value.ssrc()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for PliTraceInfoRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for PliTraceInfoRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[PliTraceInfoRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for PliTraceInfo { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for PliTraceInfoRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[PliTraceInfoRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct RtpTraceInfo { + pub is_rtx: bool, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for RtpTraceInfo { + fn default() -> Self { + Self { is_rtx: false } + } + } + + impl RtpTraceInfo { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_is_rtx: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_is_rtx = field_is_rtx.prepare(builder, &false); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 1>::new(builder); + + if prepared_is_rtx.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_is_rtx) = prepared_is_rtx { + table_writer.write::<_, _, 1>(0, &prepared_is_rtx); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RtpTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RtpTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RtpTraceInfo { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + RtpTraceInfo::create(builder, &self.is_rtx) + } + } + + #[derive(Copy, Clone)] + pub struct RtpTraceInfoRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RtpTraceInfoRef<'a> { + pub fn is_rtx(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "RtpTraceInfo", "is_rtx")?.unwrap_or(false), + ) + } + } + + impl<'a> ::core::fmt::Debug for RtpTraceInfoRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RtpTraceInfoRef"); + f.field("is_rtx", &self.is_rtx()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RtpTraceInfo { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RtpTraceInfoRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + is_rtx: ::core::convert::TryInto::try_into(value.is_rtx()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RtpTraceInfoRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RtpTraceInfoRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RtpTraceInfoRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RtpTraceInfo { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RtpTraceInfoRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[RtpTraceInfoRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct TraceNotification { + pub type_: self::TraceType, + pub timestamp: u64, + pub direction: self::TraceDirection, + pub info: ::core::option::Option, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for TraceNotification { + fn default() -> Self { + Self { + type_: self::TraceType::Keyframe, + timestamp: 0, + direction: self::TraceDirection::DirectionIn, + info: ::core::default::Default::default(), + } + } + } + + impl TraceNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_type_: impl ::planus::WriteAsDefault, + field_timestamp: impl ::planus::WriteAsDefault, + field_direction: impl ::planus::WriteAsDefault< + self::TraceDirection, + self::TraceDirection, + >, + field_info: impl ::planus::WriteAsOptionalUnion, + ) -> ::planus::Offset { + let prepared_type_ = field_type_.prepare(builder, &self::TraceType::Keyframe); + + let prepared_timestamp = field_timestamp.prepare(builder, &0); + + let prepared_direction = + field_direction.prepare(builder, &self::TraceDirection::DirectionIn); + + let prepared_info = field_info.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<10, 15>::new(builder); + + if prepared_type_.is_some() { + table_writer.calculate_size::(2); + } + if prepared_timestamp.is_some() { + table_writer.calculate_size::(4); + } + if prepared_direction.is_some() { + table_writer.calculate_size::(6); + } + if prepared_info.is_some() { + table_writer.calculate_size::(8); + table_writer.calculate_size::<::planus::Offset>(10); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_timestamp) = prepared_timestamp + { + table_writer.write::<_, _, 8>(1, &prepared_timestamp); + } + if let ::core::option::Option::Some(prepared_info) = prepared_info { + table_writer.write::<_, _, 4>(4, &prepared_info.offset()); + } + if let ::core::option::Option::Some(prepared_type_) = prepared_type_ { + table_writer.write::<_, _, 1>(0, &prepared_type_); + } + if let ::core::option::Option::Some(prepared_direction) = prepared_direction + { + table_writer.write::<_, _, 1>(2, &prepared_direction); + } + if let ::core::option::Option::Some(prepared_info) = prepared_info { + table_writer.write::<_, _, 1>(3, &prepared_info.tag()); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for TraceNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for TraceNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for TraceNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + TraceNotification::create( + builder, + &self.type_, + &self.timestamp, + &self.direction, + &self.info, + ) + } + } + + #[derive(Copy, Clone)] + pub struct TraceNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> TraceNotificationRef<'a> { + pub fn type_(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "TraceNotification", "type_")? + .unwrap_or(self::TraceType::Keyframe), + ) + } + + pub fn timestamp(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "TraceNotification", "timestamp")? + .unwrap_or(0), + ) + } + + pub fn direction(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "TraceNotification", "direction")? + .unwrap_or(self::TraceDirection::DirectionIn), + ) + } + + pub fn info( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access_union(3, "TraceNotification", "info") + } + } + + impl<'a> ::core::fmt::Debug for TraceNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("TraceNotificationRef"); + f.field("type_", &self.type_()); + f.field("timestamp", &self.timestamp()); + f.field("direction", &self.direction()); + if let ::core::option::Option::Some(field_info) = self.info().transpose() { + f.field("info", &field_info); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for TraceNotification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: TraceNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + type_: ::core::convert::TryInto::try_into(value.type_()?)?, + timestamp: ::core::convert::TryInto::try_into(value.timestamp()?)?, + direction: ::core::convert::TryInto::try_into(value.direction()?)?, + info: if let ::core::option::Option::Some(info) = value.info()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(info)?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for TraceNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for TraceNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[TraceNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for TraceNotification { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for TraceNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[TraceNotificationRef]", "read_as_root", 0) + }) + } + } + } + pub mod rtp_parameters { + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum MediaKind { + All = 0, + Audio = 1, + Video = 2, + } + + impl ::core::convert::TryFrom for MediaKind { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 0 => ::core::result::Result::Ok(MediaKind::All), + 1 => ::core::result::Result::Ok(MediaKind::Audio), + 2 => ::core::result::Result::Ok(MediaKind::Video), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: MediaKind) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for MediaKind { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for MediaKind { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for MediaKind { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> MediaKind { + *self + } + } + + impl ::planus::WriteAsDefault for MediaKind { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &MediaKind, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for MediaKind { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for MediaKind { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for MediaKind { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "MediaKind", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for MediaKind { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum Type { + None = 0, + Simple = 1, + Simulcast = 2, + Svc = 3, + Pipe = 4, + } + + impl ::core::convert::TryFrom for Type { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 0 => ::core::result::Result::Ok(Type::None), + 1 => ::core::result::Result::Ok(Type::Simple), + 2 => ::core::result::Result::Ok(Type::Simulcast), + 3 => ::core::result::Result::Ok(Type::Svc), + 4 => ::core::result::Result::Ok(Type::Pipe), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: Type) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for Type { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for Type { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for Type { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> Type { + *self + } + } + + impl ::planus::WriteAsDefault for Type { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &Type, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for Type { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for Type { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for Type { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "Type", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for Type { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Boolean { + pub value: u8, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for Boolean { + fn default() -> Self { + Self { value: 0 } + } + } + + impl Boolean { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_value: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_value = field_value.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 1>::new(builder); + + if prepared_value.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_value) = prepared_value { + table_writer.write::<_, _, 1>(0, &prepared_value); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Boolean { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Boolean { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Boolean { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Boolean::create(builder, &self.value) + } + } + + #[derive(Copy, Clone)] + pub struct BooleanRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> BooleanRef<'a> { + pub fn value(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(0, "Boolean", "value")?.unwrap_or(0)) + } + } + + impl<'a> ::core::fmt::Debug for BooleanRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("BooleanRef"); + f.field("value", &self.value()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Boolean { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: BooleanRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + value: ::core::convert::TryInto::try_into(value.value()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for BooleanRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for BooleanRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[BooleanRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Boolean { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for BooleanRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[BooleanRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Integer { + pub value: i32, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for Integer { + fn default() -> Self { + Self { value: 0 } + } + } + + impl Integer { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_value: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_value = field_value.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_value.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_value) = prepared_value { + table_writer.write::<_, _, 4>(0, &prepared_value); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Integer { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Integer { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Integer { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Integer::create(builder, &self.value) + } + } + + #[derive(Copy, Clone)] + pub struct IntegerRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> IntegerRef<'a> { + pub fn value(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(0, "Integer", "value")?.unwrap_or(0)) + } + } + + impl<'a> ::core::fmt::Debug for IntegerRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("IntegerRef"); + f.field("value", &self.value()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Integer { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: IntegerRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + value: ::core::convert::TryInto::try_into(value.value()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for IntegerRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for IntegerRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[IntegerRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Integer { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for IntegerRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[IntegerRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct IntegerArray { + pub value: ::core::option::Option<::planus::alloc::vec::Vec>, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for IntegerArray { + fn default() -> Self { + Self { + value: ::core::default::Default::default(), + } + } + } + + impl IntegerArray { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_value: impl ::planus::WriteAsOptional<::planus::Offset<[i32]>>, + ) -> ::planus::Offset { + let prepared_value = field_value.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_value.is_some() { + table_writer.calculate_size::<::planus::Offset<[i32]>>(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_value) = prepared_value { + table_writer.write::<_, _, 4>(0, &prepared_value); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for IntegerArray { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for IntegerArray { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for IntegerArray { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + IntegerArray::create(builder, &self.value) + } + } + + #[derive(Copy, Clone)] + pub struct IntegerArrayRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> IntegerArrayRef<'a> { + pub fn value( + &self, + ) -> ::planus::Result<::core::option::Option<::planus::Vector<'a, i32>>> + { + self.0.access(0, "IntegerArray", "value") + } + } + + impl<'a> ::core::fmt::Debug for IntegerArrayRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("IntegerArrayRef"); + if let ::core::option::Option::Some(field_value) = self.value().transpose() { + f.field("value", &field_value); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for IntegerArray { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: IntegerArrayRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + value: if let ::core::option::Option::Some(value) = value.value()? { + ::core::option::Option::Some(value.to_vec()?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for IntegerArrayRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for IntegerArrayRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[IntegerArrayRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for IntegerArray { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for IntegerArrayRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[IntegerArrayRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct Double { + pub value: f64, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for Double { + fn default() -> Self { + Self { value: 0.0 } + } + } + + impl Double { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_value: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_value = field_value.prepare(builder, &0.0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 8>::new(builder); + + if prepared_value.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_value) = prepared_value { + table_writer.write::<_, _, 8>(0, &prepared_value); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Double { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Double { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Double { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Double::create(builder, &self.value) + } + } + + #[derive(Copy, Clone)] + pub struct DoubleRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DoubleRef<'a> { + pub fn value(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(0, "Double", "value")?.unwrap_or(0.0)) + } + } + + impl<'a> ::core::fmt::Debug for DoubleRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DoubleRef"); + f.field("value", &self.value()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Double { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DoubleRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + value: ::core::convert::TryInto::try_into(value.value()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DoubleRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DoubleRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DoubleRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Double { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DoubleRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[DoubleRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct String { + pub value: ::core::option::Option<::planus::alloc::string::String>, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for String { + fn default() -> Self { + Self { + value: ::core::default::Default::default(), + } + } + } + + impl String { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_value: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + ) -> ::planus::Offset { + let prepared_value = field_value.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_value.is_some() { + table_writer.calculate_size::<::planus::Offset>(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_value) = prepared_value { + table_writer.write::<_, _, 4>(0, &prepared_value); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for String { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for String { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for String { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + String::create(builder, &self.value) + } + } + + #[derive(Copy, Clone)] + pub struct StringRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> StringRef<'a> { + pub fn value( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(0, "String", "value") + } + } + + impl<'a> ::core::fmt::Debug for StringRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("StringRef"); + if let ::core::option::Option::Some(field_value) = self.value().transpose() { + f.field("value", &field_value); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for String { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: StringRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + value: if let ::core::option::Option::Some(value) = value.value()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(value)?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for StringRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for StringRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[StringRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for String { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for StringRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[StringRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub enum Value { + Boolean(::planus::alloc::boxed::Box), + Integer(::planus::alloc::boxed::Box), + Double(::planus::alloc::boxed::Box), + String(::planus::alloc::boxed::Box), + IntegerArray(::planus::alloc::boxed::Box), + } + + impl Value { + pub fn create_boolean( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(1, value.prepare(builder).downcast()) + } + + pub fn create_integer( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(2, value.prepare(builder).downcast()) + } + + pub fn create_double( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(3, value.prepare(builder).downcast()) + } + + pub fn create_string( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(4, value.prepare(builder).downcast()) + } + + pub fn create_integer_array( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(5, value.prepare(builder).downcast()) + } + } + + impl ::planus::WriteAsUnion for Value { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::UnionOffset { + match self { + Self::Boolean(value) => Self::create_boolean(builder, value), + Self::Integer(value) => Self::create_integer(builder, value), + Self::Double(value) => Self::create_double(builder, value), + Self::String(value) => Self::create_string(builder, value), + Self::IntegerArray(value) => Self::create_integer_array(builder, value), + } + } + } + + impl ::planus::WriteAsOptionalUnion for Value { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::UnionOffset> { + ::core::option::Option::Some(::planus::WriteAsUnion::prepare(self, builder)) + } + } + + #[derive(Copy, Clone, Debug)] + pub enum ValueRef<'a> { + Boolean(self::BooleanRef<'a>), + Integer(self::IntegerRef<'a>), + Double(self::DoubleRef<'a>), + String(self::StringRef<'a>), + IntegerArray(self::IntegerArrayRef<'a>), + } + + impl<'a> ::core::convert::TryFrom> for Value { + type Error = ::planus::Error; + + fn try_from(value: ValueRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(match value { + ValueRef::Boolean(value) => { + Value::Boolean(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + ValueRef::Integer(value) => { + Value::Integer(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + ValueRef::Double(value) => Value::Double(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )), + + ValueRef::String(value) => Value::String(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )), + + ValueRef::IntegerArray(value) => { + Value::IntegerArray(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + }) + } + } + + impl<'a> ::planus::TableReadUnion<'a> for ValueRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + field_offset: usize, + tag: u8, + ) -> ::core::result::Result { + match tag { + 1 => ::core::result::Result::Ok(Self::Boolean( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 2 => ::core::result::Result::Ok(Self::Integer( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 3 => ::core::result::Result::Ok(Self::Double( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 4 => ::core::result::Result::Ok(Self::String( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 5 => ::core::result::Result::Ok(Self::IntegerArray( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + _ => ::core::result::Result::Err( + ::planus::errors::ErrorKind::UnknownUnionTag { tag }, + ), + } + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct Parameter { + pub name: ::planus::alloc::string::String, + pub value: ::core::option::Option, + } + + impl Parameter { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_name: impl ::planus::WriteAs<::planus::Offset>, + field_value: impl ::planus::WriteAsOptionalUnion, + ) -> ::planus::Offset { + let prepared_name = field_name.prepare(builder); + + let prepared_value = field_value.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 9>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_value.is_some() { + table_writer.calculate_size::(4); + table_writer.calculate_size::<::planus::Offset>(6); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_name); + if let ::core::option::Option::Some(prepared_value) = prepared_value { + table_writer.write::<_, _, 4>(2, &prepared_value.offset()); + } + if let ::core::option::Option::Some(prepared_value) = prepared_value { + table_writer.write::<_, _, 1>(1, &prepared_value.tag()); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Parameter { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Parameter { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Parameter { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Parameter::create(builder, &self.name, &self.value) + } + } + + #[derive(Copy, Clone)] + pub struct ParameterRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ParameterRef<'a> { + pub fn name(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "Parameter", "name") + } + + pub fn value( + &self, + ) -> ::planus::Result<::core::option::Option>> { + self.0.access_union(1, "Parameter", "value") + } + } + + impl<'a> ::core::fmt::Debug for ParameterRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ParameterRef"); + f.field("name", &self.name()); + if let ::core::option::Option::Some(field_value) = self.value().transpose() { + f.field("value", &field_value); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Parameter { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ParameterRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + name: ::core::convert::TryInto::try_into(value.name()?)?, + value: if let ::core::option::Option::Some(value) = value.value()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(value)?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ParameterRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ParameterRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ParameterRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Parameter { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ParameterRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ParameterRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct RtcpFeedback { + pub type_: ::planus::alloc::string::String, + pub parameter: ::core::option::Option<::planus::alloc::string::String>, + } + + impl RtcpFeedback { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_type_: impl ::planus::WriteAs<::planus::Offset>, + field_parameter: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + ) -> ::planus::Offset { + let prepared_type_ = field_type_.prepare(builder); + + let prepared_parameter = field_parameter.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_parameter.is_some() { + table_writer.calculate_size::<::planus::Offset>(4); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_type_); + if let ::core::option::Option::Some(prepared_parameter) = prepared_parameter + { + table_writer.write::<_, _, 4>(1, &prepared_parameter); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RtcpFeedback { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RtcpFeedback { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RtcpFeedback { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + RtcpFeedback::create(builder, &self.type_, &self.parameter) + } + } + + #[derive(Copy, Clone)] + pub struct RtcpFeedbackRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RtcpFeedbackRef<'a> { + pub fn type_(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "RtcpFeedback", "type_") + } + + pub fn parameter( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(1, "RtcpFeedback", "parameter") + } + } + + impl<'a> ::core::fmt::Debug for RtcpFeedbackRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RtcpFeedbackRef"); + f.field("type_", &self.type_()); + if let ::core::option::Option::Some(field_parameter) = + self.parameter().transpose() + { + f.field("parameter", &field_parameter); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RtcpFeedback { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RtcpFeedbackRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + type_: ::core::convert::TryInto::try_into(value.type_()?)?, + parameter: if let ::core::option::Option::Some(parameter) = + value.parameter()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + parameter, + )?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RtcpFeedbackRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RtcpFeedbackRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RtcpFeedbackRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RtcpFeedback { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RtcpFeedbackRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[RtcpFeedbackRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct RtpCodecParameters { + pub mime_type: ::planus::alloc::string::String, + pub payload_type: u8, + pub clock_rate: u32, + pub channels: ::core::option::Option, + pub parameters: ::core::option::Option<::planus::alloc::vec::Vec>, + pub rtcp_feedback: + ::core::option::Option<::planus::alloc::vec::Vec>, + } + + impl RtpCodecParameters { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_mime_type: impl ::planus::WriteAs<::planus::Offset>, + field_payload_type: impl ::planus::WriteAsDefault, + field_clock_rate: impl ::planus::WriteAsDefault, + field_channels: impl ::planus::WriteAsOptional, + field_parameters: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_rtcp_feedback: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_mime_type = field_mime_type.prepare(builder); + + let prepared_payload_type = field_payload_type.prepare(builder, &0); + + let prepared_clock_rate = field_clock_rate.prepare(builder, &0); + + let prepared_channels = field_channels.prepare(builder); + + let prepared_parameters = field_parameters.prepare(builder); + + let prepared_rtcp_feedback = field_rtcp_feedback.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<14, 18>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_payload_type.is_some() { + table_writer.calculate_size::(4); + } + if prepared_clock_rate.is_some() { + table_writer.calculate_size::(6); + } + if prepared_channels.is_some() { + table_writer.calculate_size::(8); + } + if prepared_parameters.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(10); + } + if prepared_rtcp_feedback.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(12); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_mime_type); + if let ::core::option::Option::Some(prepared_clock_rate) = + prepared_clock_rate + { + table_writer.write::<_, _, 4>(2, &prepared_clock_rate); + } + if let ::core::option::Option::Some(prepared_parameters) = + prepared_parameters + { + table_writer.write::<_, _, 4>(4, &prepared_parameters); + } + if let ::core::option::Option::Some(prepared_rtcp_feedback) = + prepared_rtcp_feedback + { + table_writer.write::<_, _, 4>(5, &prepared_rtcp_feedback); + } + if let ::core::option::Option::Some(prepared_payload_type) = + prepared_payload_type + { + table_writer.write::<_, _, 1>(1, &prepared_payload_type); + } + if let ::core::option::Option::Some(prepared_channels) = prepared_channels { + table_writer.write::<_, _, 1>(3, &prepared_channels); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RtpCodecParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RtpCodecParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RtpCodecParameters { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + RtpCodecParameters::create( + builder, + &self.mime_type, + &self.payload_type, + &self.clock_rate, + &self.channels, + &self.parameters, + &self.rtcp_feedback, + ) + } + } + + #[derive(Copy, Clone)] + pub struct RtpCodecParametersRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RtpCodecParametersRef<'a> { + pub fn mime_type(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "RtpCodecParameters", "mime_type") + } + + pub fn payload_type(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "RtpCodecParameters", "payload_type")? + .unwrap_or(0), + ) + } + + pub fn clock_rate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "RtpCodecParameters", "clock_rate")? + .unwrap_or(0), + ) + } + + pub fn channels(&self) -> ::planus::Result<::core::option::Option> { + self.0.access(3, "RtpCodecParameters", "channels") + } + + pub fn parameters( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result>>, + >, + > { + self.0.access(4, "RtpCodecParameters", "parameters") + } + + pub fn rtcp_feedback( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result>>, + >, + > { + self.0.access(5, "RtpCodecParameters", "rtcp_feedback") + } + } + + impl<'a> ::core::fmt::Debug for RtpCodecParametersRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RtpCodecParametersRef"); + f.field("mime_type", &self.mime_type()); + f.field("payload_type", &self.payload_type()); + f.field("clock_rate", &self.clock_rate()); + if let ::core::option::Option::Some(field_channels) = + self.channels().transpose() + { + f.field("channels", &field_channels); + } + if let ::core::option::Option::Some(field_parameters) = + self.parameters().transpose() + { + f.field("parameters", &field_parameters); + } + if let ::core::option::Option::Some(field_rtcp_feedback) = + self.rtcp_feedback().transpose() + { + f.field("rtcp_feedback", &field_rtcp_feedback); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RtpCodecParameters { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RtpCodecParametersRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + mime_type: ::core::convert::TryInto::try_into(value.mime_type()?)?, + payload_type: ::core::convert::TryInto::try_into(value.payload_type()?)?, + clock_rate: ::core::convert::TryInto::try_into(value.clock_rate()?)?, + channels: if let ::core::option::Option::Some(channels) = + value.channels()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + channels, + )?) + } else { + ::core::option::Option::None + }, + parameters: if let ::core::option::Option::Some(parameters) = + value.parameters()? + { + ::core::option::Option::Some(parameters.to_vec_result()?) + } else { + ::core::option::Option::None + }, + rtcp_feedback: if let ::core::option::Option::Some(rtcp_feedback) = + value.rtcp_feedback()? + { + ::core::option::Option::Some(rtcp_feedback.to_vec_result()?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RtpCodecParametersRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RtpCodecParametersRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RtpCodecParametersRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RtpCodecParameters { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RtpCodecParametersRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[RtpCodecParametersRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct RtpHeaderExtensionParameters { + pub uri: ::planus::alloc::string::String, + pub id: u8, + pub encrypt: bool, + pub parameters: ::core::option::Option<::planus::alloc::vec::Vec>, + } + + impl RtpHeaderExtensionParameters { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_uri: impl ::planus::WriteAs<::planus::Offset>, + field_id: impl ::planus::WriteAsDefault, + field_encrypt: impl ::planus::WriteAsDefault, + field_parameters: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_uri = field_uri.prepare(builder); + + let prepared_id = field_id.prepare(builder, &0); + + let prepared_encrypt = field_encrypt.prepare(builder, &false); + + let prepared_parameters = field_parameters.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<10, 10>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_id.is_some() { + table_writer.calculate_size::(4); + } + if prepared_encrypt.is_some() { + table_writer.calculate_size::(6); + } + if prepared_parameters.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(8); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_uri); + if let ::core::option::Option::Some(prepared_parameters) = + prepared_parameters + { + table_writer.write::<_, _, 4>(3, &prepared_parameters); + } + if let ::core::option::Option::Some(prepared_id) = prepared_id { + table_writer.write::<_, _, 1>(1, &prepared_id); + } + if let ::core::option::Option::Some(prepared_encrypt) = prepared_encrypt { + table_writer.write::<_, _, 1>(2, &prepared_encrypt); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for RtpHeaderExtensionParameters + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for RtpHeaderExtensionParameters + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RtpHeaderExtensionParameters { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + RtpHeaderExtensionParameters::create( + builder, + &self.uri, + &self.id, + &self.encrypt, + &self.parameters, + ) + } + } + + #[derive(Copy, Clone)] + pub struct RtpHeaderExtensionParametersRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RtpHeaderExtensionParametersRef<'a> { + pub fn uri(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "RtpHeaderExtensionParameters", "uri") + } + + pub fn id(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "RtpHeaderExtensionParameters", "id")? + .unwrap_or(0), + ) + } + + pub fn encrypt(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "RtpHeaderExtensionParameters", "encrypt")? + .unwrap_or(false), + ) + } + + pub fn parameters( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result>>, + >, + > { + self.0 + .access(3, "RtpHeaderExtensionParameters", "parameters") + } + } + + impl<'a> ::core::fmt::Debug for RtpHeaderExtensionParametersRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RtpHeaderExtensionParametersRef"); + f.field("uri", &self.uri()); + f.field("id", &self.id()); + f.field("encrypt", &self.encrypt()); + if let ::core::option::Option::Some(field_parameters) = + self.parameters().transpose() + { + f.field("parameters", &field_parameters); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for RtpHeaderExtensionParameters + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RtpHeaderExtensionParametersRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + uri: ::core::convert::TryInto::try_into(value.uri()?)?, + id: ::core::convert::TryInto::try_into(value.id()?)?, + encrypt: ::core::convert::TryInto::try_into(value.encrypt()?)?, + parameters: if let ::core::option::Option::Some(parameters) = + value.parameters()? + { + ::core::option::Option::Some(parameters.to_vec_result()?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RtpHeaderExtensionParametersRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RtpHeaderExtensionParametersRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RtpHeaderExtensionParametersRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for RtpHeaderExtensionParameters + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RtpHeaderExtensionParametersRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[RtpHeaderExtensionParametersRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Rtx { + pub ssrc: u32, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for Rtx { + fn default() -> Self { + Self { ssrc: 0 } + } + } + + impl Rtx { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ssrc: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_ssrc = field_ssrc.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_ssrc.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_ssrc) = prepared_ssrc { + table_writer.write::<_, _, 4>(0, &prepared_ssrc); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Rtx { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Rtx { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Rtx { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Rtx::create(builder, &self.ssrc) + } + } + + #[derive(Copy, Clone)] + pub struct RtxRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RtxRef<'a> { + pub fn ssrc(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(0, "Rtx", "ssrc")?.unwrap_or(0)) + } + } + + impl<'a> ::core::fmt::Debug for RtxRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RtxRef"); + f.field("ssrc", &self.ssrc()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Rtx { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RtxRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ssrc: ::core::convert::TryInto::try_into(value.ssrc()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RtxRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RtxRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location("[RtxRef]", "get", buffer.offset_from_start) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Rtx { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RtxRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[RtxRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct RtpEncodingParameters { + pub ssrc: ::core::option::Option, + pub rid: ::core::option::Option<::planus::alloc::string::String>, + pub codec_payload_type: ::core::option::Option, + pub rtx: ::core::option::Option<::planus::alloc::boxed::Box>, + pub dtx: bool, + pub scalability_mode: ::core::option::Option<::planus::alloc::string::String>, + pub max_bitrate: ::core::option::Option, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for RtpEncodingParameters { + fn default() -> Self { + Self { + ssrc: ::core::default::Default::default(), + rid: ::core::default::Default::default(), + codec_payload_type: ::core::default::Default::default(), + rtx: ::core::default::Default::default(), + dtx: false, + scalability_mode: ::core::default::Default::default(), + max_bitrate: ::core::default::Default::default(), + } + } + } + + impl RtpEncodingParameters { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ssrc: impl ::planus::WriteAsOptional, + field_rid: impl ::planus::WriteAsOptional<::planus::Offset<::core::primitive::str>>, + field_codec_payload_type: impl ::planus::WriteAsOptional, + field_rtx: impl ::planus::WriteAsOptional<::planus::Offset>, + field_dtx: impl ::planus::WriteAsDefault, + field_scalability_mode: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + field_max_bitrate: impl ::planus::WriteAsOptional, + ) -> ::planus::Offset { + let prepared_ssrc = field_ssrc.prepare(builder); + + let prepared_rid = field_rid.prepare(builder); + + let prepared_codec_payload_type = field_codec_payload_type.prepare(builder); + + let prepared_rtx = field_rtx.prepare(builder); + + let prepared_dtx = field_dtx.prepare(builder, &false); + + let prepared_scalability_mode = field_scalability_mode.prepare(builder); + + let prepared_max_bitrate = field_max_bitrate.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<16, 22>::new(builder); + + if prepared_ssrc.is_some() { + table_writer.calculate_size::(2); + } + if prepared_rid.is_some() { + table_writer.calculate_size::<::planus::Offset>(4); + } + if prepared_codec_payload_type.is_some() { + table_writer.calculate_size::(6); + } + if prepared_rtx.is_some() { + table_writer.calculate_size::<::planus::Offset>(8); + } + if prepared_dtx.is_some() { + table_writer.calculate_size::(10); + } + if prepared_scalability_mode.is_some() { + table_writer.calculate_size::<::planus::Offset>(12); + } + if prepared_max_bitrate.is_some() { + table_writer.calculate_size::(14); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_ssrc) = prepared_ssrc { + table_writer.write::<_, _, 4>(0, &prepared_ssrc); + } + if let ::core::option::Option::Some(prepared_rid) = prepared_rid { + table_writer.write::<_, _, 4>(1, &prepared_rid); + } + if let ::core::option::Option::Some(prepared_rtx) = prepared_rtx { + table_writer.write::<_, _, 4>(3, &prepared_rtx); + } + if let ::core::option::Option::Some(prepared_scalability_mode) = + prepared_scalability_mode + { + table_writer.write::<_, _, 4>(5, &prepared_scalability_mode); + } + if let ::core::option::Option::Some(prepared_max_bitrate) = + prepared_max_bitrate + { + table_writer.write::<_, _, 4>(6, &prepared_max_bitrate); + } + if let ::core::option::Option::Some(prepared_codec_payload_type) = + prepared_codec_payload_type + { + table_writer.write::<_, _, 1>(2, &prepared_codec_payload_type); + } + if let ::core::option::Option::Some(prepared_dtx) = prepared_dtx { + table_writer.write::<_, _, 1>(4, &prepared_dtx); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RtpEncodingParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RtpEncodingParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RtpEncodingParameters { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + RtpEncodingParameters::create( + builder, + &self.ssrc, + &self.rid, + &self.codec_payload_type, + &self.rtx, + &self.dtx, + &self.scalability_mode, + &self.max_bitrate, + ) + } + } + + #[derive(Copy, Clone)] + pub struct RtpEncodingParametersRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RtpEncodingParametersRef<'a> { + pub fn ssrc(&self) -> ::planus::Result<::core::option::Option> { + self.0.access(0, "RtpEncodingParameters", "ssrc") + } + + pub fn rid( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(1, "RtpEncodingParameters", "rid") + } + + pub fn codec_payload_type(&self) -> ::planus::Result<::core::option::Option> { + self.0 + .access(2, "RtpEncodingParameters", "codec_payload_type") + } + + pub fn rtx(&self) -> ::planus::Result<::core::option::Option>> { + self.0.access(3, "RtpEncodingParameters", "rtx") + } + + pub fn dtx(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(4, "RtpEncodingParameters", "dtx")? + .unwrap_or(false), + ) + } + + pub fn scalability_mode( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0 + .access(5, "RtpEncodingParameters", "scalability_mode") + } + + pub fn max_bitrate(&self) -> ::planus::Result<::core::option::Option> { + self.0.access(6, "RtpEncodingParameters", "max_bitrate") + } + } + + impl<'a> ::core::fmt::Debug for RtpEncodingParametersRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RtpEncodingParametersRef"); + if let ::core::option::Option::Some(field_ssrc) = self.ssrc().transpose() { + f.field("ssrc", &field_ssrc); + } + if let ::core::option::Option::Some(field_rid) = self.rid().transpose() { + f.field("rid", &field_rid); + } + if let ::core::option::Option::Some(field_codec_payload_type) = + self.codec_payload_type().transpose() + { + f.field("codec_payload_type", &field_codec_payload_type); + } + if let ::core::option::Option::Some(field_rtx) = self.rtx().transpose() { + f.field("rtx", &field_rtx); + } + f.field("dtx", &self.dtx()); + if let ::core::option::Option::Some(field_scalability_mode) = + self.scalability_mode().transpose() + { + f.field("scalability_mode", &field_scalability_mode); + } + if let ::core::option::Option::Some(field_max_bitrate) = + self.max_bitrate().transpose() + { + f.field("max_bitrate", &field_max_bitrate); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RtpEncodingParameters { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RtpEncodingParametersRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ssrc: if let ::core::option::Option::Some(ssrc) = value.ssrc()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(ssrc)?) + } else { + ::core::option::Option::None + }, + rid: if let ::core::option::Option::Some(rid) = value.rid()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(rid)?) + } else { + ::core::option::Option::None + }, + codec_payload_type: if let ::core::option::Option::Some( + codec_payload_type, + ) = value.codec_payload_type()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + codec_payload_type, + )?) + } else { + ::core::option::Option::None + }, + rtx: if let ::core::option::Option::Some(rtx) = value.rtx()? { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(rtx)?, + )) + } else { + ::core::option::Option::None + }, + dtx: ::core::convert::TryInto::try_into(value.dtx()?)?, + scalability_mode: if let ::core::option::Option::Some(scalability_mode) = + value.scalability_mode()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + scalability_mode, + )?) + } else { + ::core::option::Option::None + }, + max_bitrate: if let ::core::option::Option::Some(max_bitrate) = + value.max_bitrate()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + max_bitrate, + )?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RtpEncodingParametersRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RtpEncodingParametersRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RtpEncodingParametersRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RtpEncodingParameters { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RtpEncodingParametersRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[RtpEncodingParametersRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct RtcpParameters { + pub cname: ::core::option::Option<::planus::alloc::string::String>, + pub reduced_size: bool, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for RtcpParameters { + fn default() -> Self { + Self { + cname: ::core::default::Default::default(), + reduced_size: true, + } + } + } + + impl RtcpParameters { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_cname: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + field_reduced_size: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_cname = field_cname.prepare(builder); + + let prepared_reduced_size = field_reduced_size.prepare(builder, &true); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 5>::new(builder); + + if prepared_cname.is_some() { + table_writer.calculate_size::<::planus::Offset>(2); + } + if prepared_reduced_size.is_some() { + table_writer.calculate_size::(4); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_cname) = prepared_cname { + table_writer.write::<_, _, 4>(0, &prepared_cname); + } + if let ::core::option::Option::Some(prepared_reduced_size) = + prepared_reduced_size + { + table_writer.write::<_, _, 1>(1, &prepared_reduced_size); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RtcpParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RtcpParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RtcpParameters { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + RtcpParameters::create(builder, &self.cname, &self.reduced_size) + } + } + + #[derive(Copy, Clone)] + pub struct RtcpParametersRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RtcpParametersRef<'a> { + pub fn cname( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(0, "RtcpParameters", "cname") + } + + pub fn reduced_size(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "RtcpParameters", "reduced_size")? + .unwrap_or(true), + ) + } + } + + impl<'a> ::core::fmt::Debug for RtcpParametersRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RtcpParametersRef"); + if let ::core::option::Option::Some(field_cname) = self.cname().transpose() { + f.field("cname", &field_cname); + } + f.field("reduced_size", &self.reduced_size()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RtcpParameters { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RtcpParametersRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + cname: if let ::core::option::Option::Some(cname) = value.cname()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(cname)?) + } else { + ::core::option::Option::None + }, + reduced_size: ::core::convert::TryInto::try_into(value.reduced_size()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RtcpParametersRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RtcpParametersRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RtcpParametersRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RtcpParameters { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RtcpParametersRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[RtcpParametersRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct RtpParameters { + pub mid: ::core::option::Option<::planus::alloc::string::String>, + pub codecs: ::planus::alloc::vec::Vec, + pub header_extensions: ::core::option::Option< + ::planus::alloc::vec::Vec, + >, + pub encodings: + ::core::option::Option<::planus::alloc::vec::Vec>, + pub rtcp: ::core::option::Option<::planus::alloc::boxed::Box>, + } + + impl RtpParameters { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_mid: impl ::planus::WriteAsOptional<::planus::Offset<::core::primitive::str>>, + field_codecs: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_header_extensions: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_encodings: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_rtcp: impl ::planus::WriteAsOptional<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_mid = field_mid.prepare(builder); + + let prepared_codecs = field_codecs.prepare(builder); + + let prepared_header_extensions = field_header_extensions.prepare(builder); + + let prepared_encodings = field_encodings.prepare(builder); + + let prepared_rtcp = field_rtcp.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<12, 20>::new(builder); + + if prepared_mid.is_some() { + table_writer.calculate_size::<::planus::Offset>(2); + } + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(4); + if prepared_header_extensions.is_some() { + table_writer.calculate_size::<::planus::Offset< + [::planus::Offset], + >>(6); + } + if prepared_encodings.is_some() { + table_writer.calculate_size::<::planus::Offset< + [::planus::Offset], + >>(8); + } + if prepared_rtcp.is_some() { + table_writer.calculate_size::<::planus::Offset>(10); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_mid) = prepared_mid { + table_writer.write::<_, _, 4>(0, &prepared_mid); + } + table_writer.write::<_, _, 4>(1, &prepared_codecs); + if let ::core::option::Option::Some(prepared_header_extensions) = + prepared_header_extensions + { + table_writer.write::<_, _, 4>(2, &prepared_header_extensions); + } + if let ::core::option::Option::Some(prepared_encodings) = prepared_encodings + { + table_writer.write::<_, _, 4>(3, &prepared_encodings); + } + if let ::core::option::Option::Some(prepared_rtcp) = prepared_rtcp { + table_writer.write::<_, _, 4>(4, &prepared_rtcp); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RtpParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RtpParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RtpParameters { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + RtpParameters::create( + builder, + &self.mid, + &self.codecs, + &self.header_extensions, + &self.encodings, + &self.rtcp, + ) + } + } + + #[derive(Copy, Clone)] + pub struct RtpParametersRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RtpParametersRef<'a> { + pub fn mid( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(0, "RtpParameters", "mid") + } + + pub fn codecs( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result>>, + > { + self.0.access_required(1, "RtpParameters", "codecs") + } + + pub fn header_extensions( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector< + 'a, + ::planus::Result>, + >, + >, + > { + self.0.access(2, "RtpParameters", "header_extensions") + } + + pub fn encodings( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result>>, + >, + > { + self.0.access(3, "RtpParameters", "encodings") + } + + pub fn rtcp( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(4, "RtpParameters", "rtcp") + } + } + + impl<'a> ::core::fmt::Debug for RtpParametersRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RtpParametersRef"); + if let ::core::option::Option::Some(field_mid) = self.mid().transpose() { + f.field("mid", &field_mid); + } + f.field("codecs", &self.codecs()); + if let ::core::option::Option::Some(field_header_extensions) = + self.header_extensions().transpose() + { + f.field("header_extensions", &field_header_extensions); + } + if let ::core::option::Option::Some(field_encodings) = + self.encodings().transpose() + { + f.field("encodings", &field_encodings); + } + if let ::core::option::Option::Some(field_rtcp) = self.rtcp().transpose() { + f.field("rtcp", &field_rtcp); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RtpParameters { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RtpParametersRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + mid: if let ::core::option::Option::Some(mid) = value.mid()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(mid)?) + } else { + ::core::option::Option::None + }, + codecs: value.codecs()?.to_vec_result()?, + header_extensions: if let ::core::option::Option::Some(header_extensions) = + value.header_extensions()? + { + ::core::option::Option::Some(header_extensions.to_vec_result()?) + } else { + ::core::option::Option::None + }, + encodings: if let ::core::option::Option::Some(encodings) = + value.encodings()? + { + ::core::option::Option::Some(encodings.to_vec_result()?) + } else { + ::core::option::Option::None + }, + rtcp: if let ::core::option::Option::Some(rtcp) = value.rtcp()? { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(rtcp)?, + )) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RtpParametersRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RtpParametersRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RtpParametersRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RtpParameters { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RtpParametersRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[RtpParametersRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CodecMapping { + pub payload_type: u8, + pub mapped_payload_type: u8, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for CodecMapping { + fn default() -> Self { + Self { + payload_type: 0, + mapped_payload_type: 0, + } + } + } + + impl CodecMapping { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_payload_type: impl ::planus::WriteAsDefault, + field_mapped_payload_type: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_payload_type = field_payload_type.prepare(builder, &0); + + let prepared_mapped_payload_type = + field_mapped_payload_type.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 2>::new(builder); + + if prepared_payload_type.is_some() { + table_writer.calculate_size::(2); + } + if prepared_mapped_payload_type.is_some() { + table_writer.calculate_size::(4); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_payload_type) = + prepared_payload_type + { + table_writer.write::<_, _, 1>(0, &prepared_payload_type); + } + if let ::core::option::Option::Some(prepared_mapped_payload_type) = + prepared_mapped_payload_type + { + table_writer.write::<_, _, 1>(1, &prepared_mapped_payload_type); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for CodecMapping { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for CodecMapping { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CodecMapping { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CodecMapping::create(builder, &self.payload_type, &self.mapped_payload_type) + } + } + + #[derive(Copy, Clone)] + pub struct CodecMappingRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CodecMappingRef<'a> { + pub fn payload_type(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "CodecMapping", "payload_type")? + .unwrap_or(0), + ) + } + + pub fn mapped_payload_type(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "CodecMapping", "mapped_payload_type")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for CodecMappingRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CodecMappingRef"); + f.field("payload_type", &self.payload_type()); + f.field("mapped_payload_type", &self.mapped_payload_type()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for CodecMapping { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: CodecMappingRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + payload_type: ::core::convert::TryInto::try_into(value.payload_type()?)?, + mapped_payload_type: ::core::convert::TryInto::try_into( + value.mapped_payload_type()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CodecMappingRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CodecMappingRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CodecMappingRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for CodecMapping { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CodecMappingRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[CodecMappingRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct EncodingMapping { + pub rid: ::core::option::Option<::planus::alloc::string::String>, + pub ssrc: ::core::option::Option, + pub scalability_mode: ::core::option::Option<::planus::alloc::string::String>, + pub mapped_ssrc: u32, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for EncodingMapping { + fn default() -> Self { + Self { + rid: ::core::default::Default::default(), + ssrc: ::core::default::Default::default(), + scalability_mode: ::core::default::Default::default(), + mapped_ssrc: 0, + } + } + } + + impl EncodingMapping { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_rid: impl ::planus::WriteAsOptional<::planus::Offset<::core::primitive::str>>, + field_ssrc: impl ::planus::WriteAsOptional, + field_scalability_mode: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + field_mapped_ssrc: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_rid = field_rid.prepare(builder); + + let prepared_ssrc = field_ssrc.prepare(builder); + + let prepared_scalability_mode = field_scalability_mode.prepare(builder); + + let prepared_mapped_ssrc = field_mapped_ssrc.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<10, 16>::new(builder); + + if prepared_rid.is_some() { + table_writer.calculate_size::<::planus::Offset>(2); + } + if prepared_ssrc.is_some() { + table_writer.calculate_size::(4); + } + if prepared_scalability_mode.is_some() { + table_writer.calculate_size::<::planus::Offset>(6); + } + if prepared_mapped_ssrc.is_some() { + table_writer.calculate_size::(8); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_rid) = prepared_rid { + table_writer.write::<_, _, 4>(0, &prepared_rid); + } + if let ::core::option::Option::Some(prepared_ssrc) = prepared_ssrc { + table_writer.write::<_, _, 4>(1, &prepared_ssrc); + } + if let ::core::option::Option::Some(prepared_scalability_mode) = + prepared_scalability_mode + { + table_writer.write::<_, _, 4>(2, &prepared_scalability_mode); + } + if let ::core::option::Option::Some(prepared_mapped_ssrc) = + prepared_mapped_ssrc + { + table_writer.write::<_, _, 4>(3, &prepared_mapped_ssrc); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for EncodingMapping { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for EncodingMapping { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for EncodingMapping { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + EncodingMapping::create( + builder, + &self.rid, + &self.ssrc, + &self.scalability_mode, + &self.mapped_ssrc, + ) + } + } + + #[derive(Copy, Clone)] + pub struct EncodingMappingRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> EncodingMappingRef<'a> { + pub fn rid( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(0, "EncodingMapping", "rid") + } + + pub fn ssrc(&self) -> ::planus::Result<::core::option::Option> { + self.0.access(1, "EncodingMapping", "ssrc") + } + + pub fn scalability_mode( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(2, "EncodingMapping", "scalability_mode") + } + + pub fn mapped_ssrc(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(3, "EncodingMapping", "mapped_ssrc")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for EncodingMappingRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("EncodingMappingRef"); + if let ::core::option::Option::Some(field_rid) = self.rid().transpose() { + f.field("rid", &field_rid); + } + if let ::core::option::Option::Some(field_ssrc) = self.ssrc().transpose() { + f.field("ssrc", &field_ssrc); + } + if let ::core::option::Option::Some(field_scalability_mode) = + self.scalability_mode().transpose() + { + f.field("scalability_mode", &field_scalability_mode); + } + f.field("mapped_ssrc", &self.mapped_ssrc()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for EncodingMapping { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: EncodingMappingRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + rid: if let ::core::option::Option::Some(rid) = value.rid()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(rid)?) + } else { + ::core::option::Option::None + }, + ssrc: if let ::core::option::Option::Some(ssrc) = value.ssrc()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(ssrc)?) + } else { + ::core::option::Option::None + }, + scalability_mode: if let ::core::option::Option::Some(scalability_mode) = + value.scalability_mode()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + scalability_mode, + )?) + } else { + ::core::option::Option::None + }, + mapped_ssrc: ::core::convert::TryInto::try_into(value.mapped_ssrc()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for EncodingMappingRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for EncodingMappingRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[EncodingMappingRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for EncodingMapping { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for EncodingMappingRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[EncodingMappingRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct RtpMapping { + pub codecs: ::planus::alloc::vec::Vec, + pub encodings: ::planus::alloc::vec::Vec, + } + + impl RtpMapping { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_codecs: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_encodings: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_codecs = field_codecs.prepare(builder); + + let prepared_encodings = field_encodings.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer + .calculate_size::<::planus::Offset<[::planus::Offset]>>( + 2, + ); + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(4); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_codecs); + table_writer.write::<_, _, 4>(1, &prepared_encodings); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RtpMapping { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RtpMapping { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RtpMapping { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + RtpMapping::create(builder, &self.codecs, &self.encodings) + } + } + + #[derive(Copy, Clone)] + pub struct RtpMappingRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RtpMappingRef<'a> { + pub fn codecs( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result>>, + > { + self.0.access_required(0, "RtpMapping", "codecs") + } + + pub fn encodings( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result>>, + > { + self.0.access_required(1, "RtpMapping", "encodings") + } + } + + impl<'a> ::core::fmt::Debug for RtpMappingRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RtpMappingRef"); + f.field("codecs", &self.codecs()); + f.field("encodings", &self.encodings()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RtpMapping { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RtpMappingRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + codecs: value.codecs()?.to_vec_result()?, + encodings: value.encodings()?.to_vec_result()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RtpMappingRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RtpMappingRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RtpMappingRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RtpMapping { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RtpMappingRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[RtpMappingRef]", "read_as_root", 0) + }) + } + } + } + pub mod rtp_stream { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Params { + pub encoding_idx: u32, + pub ssrc: u32, + pub payload_type: u8, + pub mime_type: ::planus::alloc::string::String, + pub clock_rate: u32, + pub rid: ::core::option::Option<::planus::alloc::string::String>, + pub cname: ::planus::alloc::string::String, + pub rtx_ssrc: ::core::option::Option, + pub rtx_payload_type: ::core::option::Option, + pub use_nack: bool, + pub use_pli: bool, + pub use_fir: bool, + pub use_in_band_fec: bool, + pub use_dtx: bool, + pub spatial_layers: u8, + pub temporal_layers: u8, + } + + impl Params { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_encoding_idx: impl ::planus::WriteAsDefault, + field_ssrc: impl ::planus::WriteAsDefault, + field_payload_type: impl ::planus::WriteAsDefault, + field_mime_type: impl ::planus::WriteAs<::planus::Offset>, + field_clock_rate: impl ::planus::WriteAsDefault, + field_rid: impl ::planus::WriteAsOptional<::planus::Offset<::core::primitive::str>>, + field_cname: impl ::planus::WriteAs<::planus::Offset>, + field_rtx_ssrc: impl ::planus::WriteAsOptional, + field_rtx_payload_type: impl ::planus::WriteAsOptional, + field_use_nack: impl ::planus::WriteAsDefault, + field_use_pli: impl ::planus::WriteAsDefault, + field_use_fir: impl ::planus::WriteAsDefault, + field_use_in_band_fec: impl ::planus::WriteAsDefault, + field_use_dtx: impl ::planus::WriteAsDefault, + field_spatial_layers: impl ::planus::WriteAsDefault, + field_temporal_layers: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_encoding_idx = field_encoding_idx.prepare(builder, &0); + + let prepared_ssrc = field_ssrc.prepare(builder, &0); + + let prepared_payload_type = field_payload_type.prepare(builder, &0); + + let prepared_mime_type = field_mime_type.prepare(builder); + + let prepared_clock_rate = field_clock_rate.prepare(builder, &0); + + let prepared_rid = field_rid.prepare(builder); + + let prepared_cname = field_cname.prepare(builder); + + let prepared_rtx_ssrc = field_rtx_ssrc.prepare(builder); + + let prepared_rtx_payload_type = field_rtx_payload_type.prepare(builder); + + let prepared_use_nack = field_use_nack.prepare(builder, &false); + + let prepared_use_pli = field_use_pli.prepare(builder, &false); + + let prepared_use_fir = field_use_fir.prepare(builder, &false); + + let prepared_use_in_band_fec = field_use_in_band_fec.prepare(builder, &false); + + let prepared_use_dtx = field_use_dtx.prepare(builder, &false); + + let prepared_spatial_layers = field_spatial_layers.prepare(builder, &0); + + let prepared_temporal_layers = field_temporal_layers.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<34, 37>::new(builder); + + if prepared_encoding_idx.is_some() { + table_writer.calculate_size::(2); + } + if prepared_ssrc.is_some() { + table_writer.calculate_size::(4); + } + if prepared_payload_type.is_some() { + table_writer.calculate_size::(6); + } + table_writer.calculate_size::<::planus::Offset>(8); + if prepared_clock_rate.is_some() { + table_writer.calculate_size::(10); + } + if prepared_rid.is_some() { + table_writer.calculate_size::<::planus::Offset>(12); + } + table_writer.calculate_size::<::planus::Offset>(14); + if prepared_rtx_ssrc.is_some() { + table_writer.calculate_size::(16); + } + if prepared_rtx_payload_type.is_some() { + table_writer.calculate_size::(18); + } + if prepared_use_nack.is_some() { + table_writer.calculate_size::(20); + } + if prepared_use_pli.is_some() { + table_writer.calculate_size::(22); + } + if prepared_use_fir.is_some() { + table_writer.calculate_size::(24); + } + if prepared_use_in_band_fec.is_some() { + table_writer.calculate_size::(26); + } + if prepared_use_dtx.is_some() { + table_writer.calculate_size::(28); + } + if prepared_spatial_layers.is_some() { + table_writer.calculate_size::(30); + } + if prepared_temporal_layers.is_some() { + table_writer.calculate_size::(32); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_encoding_idx) = + prepared_encoding_idx + { + table_writer.write::<_, _, 4>(0, &prepared_encoding_idx); + } + if let ::core::option::Option::Some(prepared_ssrc) = prepared_ssrc { + table_writer.write::<_, _, 4>(1, &prepared_ssrc); + } + table_writer.write::<_, _, 4>(3, &prepared_mime_type); + if let ::core::option::Option::Some(prepared_clock_rate) = + prepared_clock_rate + { + table_writer.write::<_, _, 4>(4, &prepared_clock_rate); + } + if let ::core::option::Option::Some(prepared_rid) = prepared_rid { + table_writer.write::<_, _, 4>(5, &prepared_rid); + } + table_writer.write::<_, _, 4>(6, &prepared_cname); + if let ::core::option::Option::Some(prepared_rtx_ssrc) = prepared_rtx_ssrc { + table_writer.write::<_, _, 4>(7, &prepared_rtx_ssrc); + } + if let ::core::option::Option::Some(prepared_payload_type) = + prepared_payload_type + { + table_writer.write::<_, _, 1>(2, &prepared_payload_type); + } + if let ::core::option::Option::Some(prepared_rtx_payload_type) = + prepared_rtx_payload_type + { + table_writer.write::<_, _, 1>(8, &prepared_rtx_payload_type); + } + if let ::core::option::Option::Some(prepared_use_nack) = prepared_use_nack { + table_writer.write::<_, _, 1>(9, &prepared_use_nack); + } + if let ::core::option::Option::Some(prepared_use_pli) = prepared_use_pli { + table_writer.write::<_, _, 1>(10, &prepared_use_pli); + } + if let ::core::option::Option::Some(prepared_use_fir) = prepared_use_fir { + table_writer.write::<_, _, 1>(11, &prepared_use_fir); + } + if let ::core::option::Option::Some(prepared_use_in_band_fec) = + prepared_use_in_band_fec + { + table_writer.write::<_, _, 1>(12, &prepared_use_in_band_fec); + } + if let ::core::option::Option::Some(prepared_use_dtx) = prepared_use_dtx { + table_writer.write::<_, _, 1>(13, &prepared_use_dtx); + } + if let ::core::option::Option::Some(prepared_spatial_layers) = + prepared_spatial_layers + { + table_writer.write::<_, _, 1>(14, &prepared_spatial_layers); + } + if let ::core::option::Option::Some(prepared_temporal_layers) = + prepared_temporal_layers + { + table_writer.write::<_, _, 1>(15, &prepared_temporal_layers); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Params { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Params { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Params { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Params::create( + builder, + &self.encoding_idx, + &self.ssrc, + &self.payload_type, + &self.mime_type, + &self.clock_rate, + &self.rid, + &self.cname, + &self.rtx_ssrc, + &self.rtx_payload_type, + &self.use_nack, + &self.use_pli, + &self.use_fir, + &self.use_in_band_fec, + &self.use_dtx, + &self.spatial_layers, + &self.temporal_layers, + ) + } + } + + #[derive(Copy, Clone)] + pub struct ParamsRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ParamsRef<'a> { + pub fn encoding_idx(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "Params", "encoding_idx")?.unwrap_or(0), + ) + } + + pub fn ssrc(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(1, "Params", "ssrc")?.unwrap_or(0)) + } + + pub fn payload_type(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(2, "Params", "payload_type")?.unwrap_or(0), + ) + } + + pub fn mime_type(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(3, "Params", "mime_type") + } + + pub fn clock_rate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(4, "Params", "clock_rate")?.unwrap_or(0), + ) + } + + pub fn rid( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(5, "Params", "rid") + } + + pub fn cname(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(6, "Params", "cname") + } + + pub fn rtx_ssrc(&self) -> ::planus::Result<::core::option::Option> { + self.0.access(7, "Params", "rtx_ssrc") + } + + pub fn rtx_payload_type(&self) -> ::planus::Result<::core::option::Option> { + self.0.access(8, "Params", "rtx_payload_type") + } + + pub fn use_nack(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(9, "Params", "use_nack")?.unwrap_or(false), + ) + } + + pub fn use_pli(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(10, "Params", "use_pli")?.unwrap_or(false), + ) + } + + pub fn use_fir(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(11, "Params", "use_fir")?.unwrap_or(false), + ) + } + + pub fn use_in_band_fec(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(12, "Params", "use_in_band_fec")? + .unwrap_or(false), + ) + } + + pub fn use_dtx(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(13, "Params", "use_dtx")?.unwrap_or(false), + ) + } + + pub fn spatial_layers(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(14, "Params", "spatial_layers")?.unwrap_or(0), + ) + } + + pub fn temporal_layers(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(15, "Params", "temporal_layers")?.unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for ParamsRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ParamsRef"); + f.field("encoding_idx", &self.encoding_idx()); + f.field("ssrc", &self.ssrc()); + f.field("payload_type", &self.payload_type()); + f.field("mime_type", &self.mime_type()); + f.field("clock_rate", &self.clock_rate()); + if let ::core::option::Option::Some(field_rid) = self.rid().transpose() { + f.field("rid", &field_rid); + } + f.field("cname", &self.cname()); + if let ::core::option::Option::Some(field_rtx_ssrc) = + self.rtx_ssrc().transpose() + { + f.field("rtx_ssrc", &field_rtx_ssrc); + } + if let ::core::option::Option::Some(field_rtx_payload_type) = + self.rtx_payload_type().transpose() + { + f.field("rtx_payload_type", &field_rtx_payload_type); + } + f.field("use_nack", &self.use_nack()); + f.field("use_pli", &self.use_pli()); + f.field("use_fir", &self.use_fir()); + f.field("use_in_band_fec", &self.use_in_band_fec()); + f.field("use_dtx", &self.use_dtx()); + f.field("spatial_layers", &self.spatial_layers()); + f.field("temporal_layers", &self.temporal_layers()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Params { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ParamsRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + encoding_idx: ::core::convert::TryInto::try_into(value.encoding_idx()?)?, + ssrc: ::core::convert::TryInto::try_into(value.ssrc()?)?, + payload_type: ::core::convert::TryInto::try_into(value.payload_type()?)?, + mime_type: ::core::convert::TryInto::try_into(value.mime_type()?)?, + clock_rate: ::core::convert::TryInto::try_into(value.clock_rate()?)?, + rid: if let ::core::option::Option::Some(rid) = value.rid()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(rid)?) + } else { + ::core::option::Option::None + }, + cname: ::core::convert::TryInto::try_into(value.cname()?)?, + rtx_ssrc: if let ::core::option::Option::Some(rtx_ssrc) = + value.rtx_ssrc()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + rtx_ssrc, + )?) + } else { + ::core::option::Option::None + }, + rtx_payload_type: if let ::core::option::Option::Some(rtx_payload_type) = + value.rtx_payload_type()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + rtx_payload_type, + )?) + } else { + ::core::option::Option::None + }, + use_nack: ::core::convert::TryInto::try_into(value.use_nack()?)?, + use_pli: ::core::convert::TryInto::try_into(value.use_pli()?)?, + use_fir: ::core::convert::TryInto::try_into(value.use_fir()?)?, + use_in_band_fec: ::core::convert::TryInto::try_into( + value.use_in_band_fec()?, + )?, + use_dtx: ::core::convert::TryInto::try_into(value.use_dtx()?)?, + spatial_layers: ::core::convert::TryInto::try_into( + value.spatial_layers()?, + )?, + temporal_layers: ::core::convert::TryInto::try_into( + value.temporal_layers()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ParamsRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ParamsRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ParamsRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Params { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ParamsRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ParamsRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Dump { + pub params: ::planus::alloc::boxed::Box, + pub score: u8, + pub rtx_stream: + ::core::option::Option<::planus::alloc::boxed::Box>, + } + + impl Dump { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_params: impl ::planus::WriteAs<::planus::Offset>, + field_score: impl ::planus::WriteAsDefault, + field_rtx_stream: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_params = field_params.prepare(builder); + + let prepared_score = field_score.prepare(builder, &0); + + let prepared_rtx_stream = field_rtx_stream.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<8, 9>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_score.is_some() { + table_writer.calculate_size::(4); + } + if prepared_rtx_stream.is_some() { + table_writer + .calculate_size::<::planus::Offset>(6); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_params); + if let ::core::option::Option::Some(prepared_rtx_stream) = + prepared_rtx_stream + { + table_writer.write::<_, _, 4>(2, &prepared_rtx_stream); + } + if let ::core::option::Option::Some(prepared_score) = prepared_score { + table_writer.write::<_, _, 1>(1, &prepared_score); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Dump { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Dump { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Dump { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Dump::create(builder, &self.params, &self.score, &self.rtx_stream) + } + } + + #[derive(Copy, Clone)] + pub struct DumpRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DumpRef<'a> { + pub fn params(&self) -> ::planus::Result> { + self.0.access_required(0, "Dump", "params") + } + + pub fn score(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(1, "Dump", "score")?.unwrap_or(0)) + } + + pub fn rtx_stream( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(2, "Dump", "rtx_stream") + } + } + + impl<'a> ::core::fmt::Debug for DumpRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DumpRef"); + f.field("params", &self.params()); + f.field("score", &self.score()); + if let ::core::option::Option::Some(field_rtx_stream) = + self.rtx_stream().transpose() + { + f.field("rtx_stream", &field_rtx_stream); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Dump { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DumpRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + params: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.params()?)?, + ), + score: ::core::convert::TryInto::try_into(value.score()?)?, + rtx_stream: if let ::core::option::Option::Some(rtx_stream) = + value.rtx_stream()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(rtx_stream)?, + )) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DumpRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DumpRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location("[DumpRef]", "get", buffer.offset_from_start) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Dump { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DumpRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[DumpRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct BitrateByLayer { + pub layer: ::planus::alloc::string::String, + pub bitrate: u64, + } + + impl BitrateByLayer { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_layer: impl ::planus::WriteAs<::planus::Offset>, + field_bitrate: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_layer = field_layer.prepare(builder); + + let prepared_bitrate = field_bitrate.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 12>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_bitrate.is_some() { + table_writer.calculate_size::(4); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_bitrate) = prepared_bitrate { + table_writer.write::<_, _, 8>(1, &prepared_bitrate); + } + table_writer.write::<_, _, 4>(0, &prepared_layer); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for BitrateByLayer { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for BitrateByLayer { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for BitrateByLayer { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + BitrateByLayer::create(builder, &self.layer, &self.bitrate) + } + } + + #[derive(Copy, Clone)] + pub struct BitrateByLayerRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> BitrateByLayerRef<'a> { + pub fn layer(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "BitrateByLayer", "layer") + } + + pub fn bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(1, "BitrateByLayer", "bitrate")?.unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for BitrateByLayerRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("BitrateByLayerRef"); + f.field("layer", &self.layer()); + f.field("bitrate", &self.bitrate()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for BitrateByLayer { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: BitrateByLayerRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + layer: ::core::convert::TryInto::try_into(value.layer()?)?, + bitrate: ::core::convert::TryInto::try_into(value.bitrate()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for BitrateByLayerRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for BitrateByLayerRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[BitrateByLayerRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for BitrateByLayer { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for BitrateByLayerRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[BitrateByLayerRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub enum StatsData { + BaseStats(::planus::alloc::boxed::Box), + RecvStats(::planus::alloc::boxed::Box), + SendStats(::planus::alloc::boxed::Box), + } + + impl StatsData { + pub fn create_base_stats( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(1, value.prepare(builder).downcast()) + } + + pub fn create_recv_stats( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(2, value.prepare(builder).downcast()) + } + + pub fn create_send_stats( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(3, value.prepare(builder).downcast()) + } + } + + impl ::planus::WriteAsUnion for StatsData { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::UnionOffset { + match self { + Self::BaseStats(value) => Self::create_base_stats(builder, value), + Self::RecvStats(value) => Self::create_recv_stats(builder, value), + Self::SendStats(value) => Self::create_send_stats(builder, value), + } + } + } + + impl ::planus::WriteAsOptionalUnion for StatsData { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::UnionOffset> { + ::core::option::Option::Some(::planus::WriteAsUnion::prepare(self, builder)) + } + } + + #[derive(Copy, Clone, Debug)] + pub enum StatsDataRef<'a> { + BaseStats(self::BaseStatsRef<'a>), + RecvStats(self::RecvStatsRef<'a>), + SendStats(self::SendStatsRef<'a>), + } + + impl<'a> ::core::convert::TryFrom> for StatsData { + type Error = ::planus::Error; + + fn try_from(value: StatsDataRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(match value { + StatsDataRef::BaseStats(value) => { + StatsData::BaseStats(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + StatsDataRef::RecvStats(value) => { + StatsData::RecvStats(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + StatsDataRef::SendStats(value) => { + StatsData::SendStats(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + }) + } + } + + impl<'a> ::planus::TableReadUnion<'a> for StatsDataRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + field_offset: usize, + tag: u8, + ) -> ::core::result::Result { + match tag { + 1 => ::core::result::Result::Ok(Self::BaseStats( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 2 => ::core::result::Result::Ok(Self::RecvStats( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 3 => ::core::result::Result::Ok(Self::SendStats( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + _ => ::core::result::Result::Err( + ::planus::errors::ErrorKind::UnknownUnionTag { tag }, + ), + } + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct Stats { + pub data: ::core::option::Option, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for Stats { + fn default() -> Self { + Self { + data: ::core::default::Default::default(), + } + } + } + + impl Stats { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_data: impl ::planus::WriteAsOptionalUnion, + ) -> ::planus::Offset { + let prepared_data = field_data.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 5>::new(builder); + + if prepared_data.is_some() { + table_writer.calculate_size::(2); + table_writer.calculate_size::<::planus::Offset>(4); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_data) = prepared_data { + table_writer.write::<_, _, 4>(1, &prepared_data.offset()); + } + if let ::core::option::Option::Some(prepared_data) = prepared_data { + table_writer.write::<_, _, 1>(0, &prepared_data.tag()); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Stats { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Stats { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Stats { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Stats::create(builder, &self.data) + } + } + + #[derive(Copy, Clone)] + pub struct StatsRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> StatsRef<'a> { + pub fn data( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access_union(0, "Stats", "data") + } + } + + impl<'a> ::core::fmt::Debug for StatsRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("StatsRef"); + if let ::core::option::Option::Some(field_data) = self.data().transpose() { + f.field("data", &field_data); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Stats { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: StatsRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + data: if let ::core::option::Option::Some(data) = value.data()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(data)?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for StatsRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for StatsRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[StatsRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Stats { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for StatsRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[StatsRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct BaseStats { + pub timestamp: u64, + pub ssrc: u32, + pub kind: super::rtp_parameters::MediaKind, + pub mime_type: ::planus::alloc::string::String, + pub packets_lost: u64, + pub fraction_lost: u64, + pub packets_discarded: u64, + pub packets_retransmitted: u64, + pub packets_repaired: u64, + pub nack_count: u64, + pub nack_packet_count: u64, + pub pli_count: u64, + pub fir_count: u64, + pub score: u8, + pub rid: ::core::option::Option<::planus::alloc::string::String>, + pub rtx_ssrc: ::core::option::Option, + pub rtx_packets_discarded: u64, + pub round_trip_time: f32, + } + + impl BaseStats { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_timestamp: impl ::planus::WriteAsDefault, + field_ssrc: impl ::planus::WriteAsDefault, + field_kind: impl ::planus::WriteAsDefault< + super::rtp_parameters::MediaKind, + super::rtp_parameters::MediaKind, + >, + field_mime_type: impl ::planus::WriteAs<::planus::Offset>, + field_packets_lost: impl ::planus::WriteAsDefault, + field_fraction_lost: impl ::planus::WriteAsDefault, + field_packets_discarded: impl ::planus::WriteAsDefault, + field_packets_retransmitted: impl ::planus::WriteAsDefault, + field_packets_repaired: impl ::planus::WriteAsDefault, + field_nack_count: impl ::planus::WriteAsDefault, + field_nack_packet_count: impl ::planus::WriteAsDefault, + field_pli_count: impl ::planus::WriteAsDefault, + field_fir_count: impl ::planus::WriteAsDefault, + field_score: impl ::planus::WriteAsDefault, + field_rid: impl ::planus::WriteAsOptional<::planus::Offset<::core::primitive::str>>, + field_rtx_ssrc: impl ::planus::WriteAsOptional, + field_rtx_packets_discarded: impl ::planus::WriteAsDefault, + field_round_trip_time: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_timestamp = field_timestamp.prepare(builder, &0); + + let prepared_ssrc = field_ssrc.prepare(builder, &0); + + let prepared_kind = + field_kind.prepare(builder, &super::rtp_parameters::MediaKind::All); + + let prepared_mime_type = field_mime_type.prepare(builder); + + let prepared_packets_lost = field_packets_lost.prepare(builder, &0); + + let prepared_fraction_lost = field_fraction_lost.prepare(builder, &0); + + let prepared_packets_discarded = field_packets_discarded.prepare(builder, &0); + + let prepared_packets_retransmitted = + field_packets_retransmitted.prepare(builder, &0); + + let prepared_packets_repaired = field_packets_repaired.prepare(builder, &0); + + let prepared_nack_count = field_nack_count.prepare(builder, &0); + + let prepared_nack_packet_count = field_nack_packet_count.prepare(builder, &0); + + let prepared_pli_count = field_pli_count.prepare(builder, &0); + + let prepared_fir_count = field_fir_count.prepare(builder, &0); + + let prepared_score = field_score.prepare(builder, &0); + + let prepared_rid = field_rid.prepare(builder); + + let prepared_rtx_ssrc = field_rtx_ssrc.prepare(builder); + + let prepared_rtx_packets_discarded = + field_rtx_packets_discarded.prepare(builder, &0); + + let prepared_round_trip_time = field_round_trip_time.prepare(builder, &0.0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<38, 110>::new(builder); + + if prepared_timestamp.is_some() { + table_writer.calculate_size::(2); + } + if prepared_ssrc.is_some() { + table_writer.calculate_size::(4); + } + if prepared_kind.is_some() { + table_writer.calculate_size::(6); + } + table_writer.calculate_size::<::planus::Offset>(8); + if prepared_packets_lost.is_some() { + table_writer.calculate_size::(10); + } + if prepared_fraction_lost.is_some() { + table_writer.calculate_size::(12); + } + if prepared_packets_discarded.is_some() { + table_writer.calculate_size::(14); + } + if prepared_packets_retransmitted.is_some() { + table_writer.calculate_size::(16); + } + if prepared_packets_repaired.is_some() { + table_writer.calculate_size::(18); + } + if prepared_nack_count.is_some() { + table_writer.calculate_size::(20); + } + if prepared_nack_packet_count.is_some() { + table_writer.calculate_size::(22); + } + if prepared_pli_count.is_some() { + table_writer.calculate_size::(24); + } + if prepared_fir_count.is_some() { + table_writer.calculate_size::(26); + } + if prepared_score.is_some() { + table_writer.calculate_size::(28); + } + if prepared_rid.is_some() { + table_writer.calculate_size::<::planus::Offset>(30); + } + if prepared_rtx_ssrc.is_some() { + table_writer.calculate_size::(32); + } + if prepared_rtx_packets_discarded.is_some() { + table_writer.calculate_size::(34); + } + if prepared_round_trip_time.is_some() { + table_writer.calculate_size::(36); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_timestamp) = prepared_timestamp + { + table_writer.write::<_, _, 8>(0, &prepared_timestamp); + } + if let ::core::option::Option::Some(prepared_packets_lost) = + prepared_packets_lost + { + table_writer.write::<_, _, 8>(4, &prepared_packets_lost); + } + if let ::core::option::Option::Some(prepared_fraction_lost) = + prepared_fraction_lost + { + table_writer.write::<_, _, 8>(5, &prepared_fraction_lost); + } + if let ::core::option::Option::Some(prepared_packets_discarded) = + prepared_packets_discarded + { + table_writer.write::<_, _, 8>(6, &prepared_packets_discarded); + } + if let ::core::option::Option::Some(prepared_packets_retransmitted) = + prepared_packets_retransmitted + { + table_writer.write::<_, _, 8>(7, &prepared_packets_retransmitted); + } + if let ::core::option::Option::Some(prepared_packets_repaired) = + prepared_packets_repaired + { + table_writer.write::<_, _, 8>(8, &prepared_packets_repaired); + } + if let ::core::option::Option::Some(prepared_nack_count) = + prepared_nack_count + { + table_writer.write::<_, _, 8>(9, &prepared_nack_count); + } + if let ::core::option::Option::Some(prepared_nack_packet_count) = + prepared_nack_packet_count + { + table_writer.write::<_, _, 8>(10, &prepared_nack_packet_count); + } + if let ::core::option::Option::Some(prepared_pli_count) = prepared_pli_count + { + table_writer.write::<_, _, 8>(11, &prepared_pli_count); + } + if let ::core::option::Option::Some(prepared_fir_count) = prepared_fir_count + { + table_writer.write::<_, _, 8>(12, &prepared_fir_count); + } + if let ::core::option::Option::Some(prepared_rtx_packets_discarded) = + prepared_rtx_packets_discarded + { + table_writer.write::<_, _, 8>(16, &prepared_rtx_packets_discarded); + } + if let ::core::option::Option::Some(prepared_ssrc) = prepared_ssrc { + table_writer.write::<_, _, 4>(1, &prepared_ssrc); + } + table_writer.write::<_, _, 4>(3, &prepared_mime_type); + if let ::core::option::Option::Some(prepared_rid) = prepared_rid { + table_writer.write::<_, _, 4>(14, &prepared_rid); + } + if let ::core::option::Option::Some(prepared_rtx_ssrc) = prepared_rtx_ssrc { + table_writer.write::<_, _, 4>(15, &prepared_rtx_ssrc); + } + if let ::core::option::Option::Some(prepared_round_trip_time) = + prepared_round_trip_time + { + table_writer.write::<_, _, 4>(17, &prepared_round_trip_time); + } + if let ::core::option::Option::Some(prepared_kind) = prepared_kind { + table_writer.write::<_, _, 1>(2, &prepared_kind); + } + if let ::core::option::Option::Some(prepared_score) = prepared_score { + table_writer.write::<_, _, 1>(13, &prepared_score); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for BaseStats { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for BaseStats { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for BaseStats { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + BaseStats::create( + builder, + &self.timestamp, + &self.ssrc, + &self.kind, + &self.mime_type, + &self.packets_lost, + &self.fraction_lost, + &self.packets_discarded, + &self.packets_retransmitted, + &self.packets_repaired, + &self.nack_count, + &self.nack_packet_count, + &self.pli_count, + &self.fir_count, + &self.score, + &self.rid, + &self.rtx_ssrc, + &self.rtx_packets_discarded, + &self.round_trip_time, + ) + } + } + + #[derive(Copy, Clone)] + pub struct BaseStatsRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> BaseStatsRef<'a> { + pub fn timestamp(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "BaseStats", "timestamp")?.unwrap_or(0), + ) + } + + pub fn ssrc(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(1, "BaseStats", "ssrc")?.unwrap_or(0)) + } + + pub fn kind(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "BaseStats", "kind")? + .unwrap_or(super::rtp_parameters::MediaKind::All), + ) + } + + pub fn mime_type(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(3, "BaseStats", "mime_type") + } + + pub fn packets_lost(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(4, "BaseStats", "packets_lost")?.unwrap_or(0), + ) + } + + pub fn fraction_lost(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(5, "BaseStats", "fraction_lost")?.unwrap_or(0), + ) + } + + pub fn packets_discarded(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(6, "BaseStats", "packets_discarded")? + .unwrap_or(0), + ) + } + + pub fn packets_retransmitted(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(7, "BaseStats", "packets_retransmitted")? + .unwrap_or(0), + ) + } + + pub fn packets_repaired(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(8, "BaseStats", "packets_repaired")? + .unwrap_or(0), + ) + } + + pub fn nack_count(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(9, "BaseStats", "nack_count")?.unwrap_or(0), + ) + } + + pub fn nack_packet_count(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(10, "BaseStats", "nack_packet_count")? + .unwrap_or(0), + ) + } + + pub fn pli_count(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(11, "BaseStats", "pli_count")?.unwrap_or(0), + ) + } + + pub fn fir_count(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(12, "BaseStats", "fir_count")?.unwrap_or(0), + ) + } + + pub fn score(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(13, "BaseStats", "score")?.unwrap_or(0), + ) + } + + pub fn rid( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(14, "BaseStats", "rid") + } + + pub fn rtx_ssrc(&self) -> ::planus::Result<::core::option::Option> { + self.0.access(15, "BaseStats", "rtx_ssrc") + } + + pub fn rtx_packets_discarded(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(16, "BaseStats", "rtx_packets_discarded")? + .unwrap_or(0), + ) + } + + pub fn round_trip_time(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(17, "BaseStats", "round_trip_time")? + .unwrap_or(0.0), + ) + } + } + + impl<'a> ::core::fmt::Debug for BaseStatsRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("BaseStatsRef"); + f.field("timestamp", &self.timestamp()); + f.field("ssrc", &self.ssrc()); + f.field("kind", &self.kind()); + f.field("mime_type", &self.mime_type()); + f.field("packets_lost", &self.packets_lost()); + f.field("fraction_lost", &self.fraction_lost()); + f.field("packets_discarded", &self.packets_discarded()); + f.field("packets_retransmitted", &self.packets_retransmitted()); + f.field("packets_repaired", &self.packets_repaired()); + f.field("nack_count", &self.nack_count()); + f.field("nack_packet_count", &self.nack_packet_count()); + f.field("pli_count", &self.pli_count()); + f.field("fir_count", &self.fir_count()); + f.field("score", &self.score()); + if let ::core::option::Option::Some(field_rid) = self.rid().transpose() { + f.field("rid", &field_rid); + } + if let ::core::option::Option::Some(field_rtx_ssrc) = + self.rtx_ssrc().transpose() + { + f.field("rtx_ssrc", &field_rtx_ssrc); + } + f.field("rtx_packets_discarded", &self.rtx_packets_discarded()); + f.field("round_trip_time", &self.round_trip_time()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for BaseStats { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: BaseStatsRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + timestamp: ::core::convert::TryInto::try_into(value.timestamp()?)?, + ssrc: ::core::convert::TryInto::try_into(value.ssrc()?)?, + kind: ::core::convert::TryInto::try_into(value.kind()?)?, + mime_type: ::core::convert::TryInto::try_into(value.mime_type()?)?, + packets_lost: ::core::convert::TryInto::try_into(value.packets_lost()?)?, + fraction_lost: ::core::convert::TryInto::try_into(value.fraction_lost()?)?, + packets_discarded: ::core::convert::TryInto::try_into( + value.packets_discarded()?, + )?, + packets_retransmitted: ::core::convert::TryInto::try_into( + value.packets_retransmitted()?, + )?, + packets_repaired: ::core::convert::TryInto::try_into( + value.packets_repaired()?, + )?, + nack_count: ::core::convert::TryInto::try_into(value.nack_count()?)?, + nack_packet_count: ::core::convert::TryInto::try_into( + value.nack_packet_count()?, + )?, + pli_count: ::core::convert::TryInto::try_into(value.pli_count()?)?, + fir_count: ::core::convert::TryInto::try_into(value.fir_count()?)?, + score: ::core::convert::TryInto::try_into(value.score()?)?, + rid: if let ::core::option::Option::Some(rid) = value.rid()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(rid)?) + } else { + ::core::option::Option::None + }, + rtx_ssrc: if let ::core::option::Option::Some(rtx_ssrc) = + value.rtx_ssrc()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + rtx_ssrc, + )?) + } else { + ::core::option::Option::None + }, + rtx_packets_discarded: ::core::convert::TryInto::try_into( + value.rtx_packets_discarded()?, + )?, + round_trip_time: ::core::convert::TryInto::try_into( + value.round_trip_time()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for BaseStatsRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for BaseStatsRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[BaseStatsRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for BaseStats { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for BaseStatsRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[BaseStatsRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct RecvStats { + pub base: ::planus::alloc::boxed::Box, + pub jitter: u32, + pub packet_count: u64, + pub byte_count: u64, + pub bitrate: u64, + pub bitrate_by_layer: + ::core::option::Option<::planus::alloc::vec::Vec>, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for RecvStats { + fn default() -> Self { + Self { + base: ::core::default::Default::default(), + jitter: 0, + packet_count: 0, + byte_count: 0, + bitrate: 0, + bitrate_by_layer: ::core::default::Default::default(), + } + } + } + + impl RecvStats { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + field_jitter: impl ::planus::WriteAsDefault, + field_packet_count: impl ::planus::WriteAsDefault, + field_byte_count: impl ::planus::WriteAsDefault, + field_bitrate: impl ::planus::WriteAsDefault, + field_bitrate_by_layer: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let prepared_jitter = field_jitter.prepare(builder, &0); + + let prepared_packet_count = field_packet_count.prepare(builder, &0); + + let prepared_byte_count = field_byte_count.prepare(builder, &0); + + let prepared_bitrate = field_bitrate.prepare(builder, &0); + + let prepared_bitrate_by_layer = field_bitrate_by_layer.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<14, 36>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_jitter.is_some() { + table_writer.calculate_size::(4); + } + if prepared_packet_count.is_some() { + table_writer.calculate_size::(6); + } + if prepared_byte_count.is_some() { + table_writer.calculate_size::(8); + } + if prepared_bitrate.is_some() { + table_writer.calculate_size::(10); + } + if prepared_bitrate_by_layer.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(12); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_packet_count) = + prepared_packet_count + { + table_writer.write::<_, _, 8>(2, &prepared_packet_count); + } + if let ::core::option::Option::Some(prepared_byte_count) = + prepared_byte_count + { + table_writer.write::<_, _, 8>(3, &prepared_byte_count); + } + if let ::core::option::Option::Some(prepared_bitrate) = prepared_bitrate { + table_writer.write::<_, _, 8>(4, &prepared_bitrate); + } + table_writer.write::<_, _, 4>(0, &prepared_base); + if let ::core::option::Option::Some(prepared_jitter) = prepared_jitter { + table_writer.write::<_, _, 4>(1, &prepared_jitter); + } + if let ::core::option::Option::Some(prepared_bitrate_by_layer) = + prepared_bitrate_by_layer + { + table_writer.write::<_, _, 4>(5, &prepared_bitrate_by_layer); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RecvStats { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RecvStats { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RecvStats { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + RecvStats::create( + builder, + &self.base, + &self.jitter, + &self.packet_count, + &self.byte_count, + &self.bitrate, + &self.bitrate_by_layer, + ) + } + } + + #[derive(Copy, Clone)] + pub struct RecvStatsRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RecvStatsRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "RecvStats", "base") + } + + pub fn jitter(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(1, "RecvStats", "jitter")?.unwrap_or(0), + ) + } + + pub fn packet_count(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(2, "RecvStats", "packet_count")?.unwrap_or(0), + ) + } + + pub fn byte_count(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(3, "RecvStats", "byte_count")?.unwrap_or(0), + ) + } + + pub fn bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(4, "RecvStats", "bitrate")?.unwrap_or(0), + ) + } + + pub fn bitrate_by_layer( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result>>, + >, + > { + self.0.access(5, "RecvStats", "bitrate_by_layer") + } + } + + impl<'a> ::core::fmt::Debug for RecvStatsRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RecvStatsRef"); + f.field("base", &self.base()); + f.field("jitter", &self.jitter()); + f.field("packet_count", &self.packet_count()); + f.field("byte_count", &self.byte_count()); + f.field("bitrate", &self.bitrate()); + if let ::core::option::Option::Some(field_bitrate_by_layer) = + self.bitrate_by_layer().transpose() + { + f.field("bitrate_by_layer", &field_bitrate_by_layer); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RecvStats { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RecvStatsRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + jitter: ::core::convert::TryInto::try_into(value.jitter()?)?, + packet_count: ::core::convert::TryInto::try_into(value.packet_count()?)?, + byte_count: ::core::convert::TryInto::try_into(value.byte_count()?)?, + bitrate: ::core::convert::TryInto::try_into(value.bitrate()?)?, + bitrate_by_layer: if let ::core::option::Option::Some(bitrate_by_layer) = + value.bitrate_by_layer()? + { + ::core::option::Option::Some(bitrate_by_layer.to_vec_result()?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RecvStatsRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RecvStatsRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RecvStatsRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RecvStats { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RecvStatsRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[RecvStatsRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct SendStats { + pub base: ::planus::alloc::boxed::Box, + pub packet_count: u64, + pub byte_count: u64, + pub bitrate: u64, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for SendStats { + fn default() -> Self { + Self { + base: ::core::default::Default::default(), + packet_count: 0, + byte_count: 0, + bitrate: 0, + } + } + } + + impl SendStats { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + field_packet_count: impl ::planus::WriteAsDefault, + field_byte_count: impl ::planus::WriteAsDefault, + field_bitrate: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let prepared_packet_count = field_packet_count.prepare(builder, &0); + + let prepared_byte_count = field_byte_count.prepare(builder, &0); + + let prepared_bitrate = field_bitrate.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<10, 28>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_packet_count.is_some() { + table_writer.calculate_size::(4); + } + if prepared_byte_count.is_some() { + table_writer.calculate_size::(6); + } + if prepared_bitrate.is_some() { + table_writer.calculate_size::(8); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_packet_count) = + prepared_packet_count + { + table_writer.write::<_, _, 8>(1, &prepared_packet_count); + } + if let ::core::option::Option::Some(prepared_byte_count) = + prepared_byte_count + { + table_writer.write::<_, _, 8>(2, &prepared_byte_count); + } + if let ::core::option::Option::Some(prepared_bitrate) = prepared_bitrate { + table_writer.write::<_, _, 8>(3, &prepared_bitrate); + } + table_writer.write::<_, _, 4>(0, &prepared_base); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for SendStats { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for SendStats { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SendStats { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + SendStats::create( + builder, + &self.base, + &self.packet_count, + &self.byte_count, + &self.bitrate, + ) + } + } + + #[derive(Copy, Clone)] + pub struct SendStatsRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SendStatsRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "SendStats", "base") + } + + pub fn packet_count(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(1, "SendStats", "packet_count")?.unwrap_or(0), + ) + } + + pub fn byte_count(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(2, "SendStats", "byte_count")?.unwrap_or(0), + ) + } + + pub fn bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(3, "SendStats", "bitrate")?.unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for SendStatsRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SendStatsRef"); + f.field("base", &self.base()); + f.field("packet_count", &self.packet_count()); + f.field("byte_count", &self.byte_count()); + f.field("bitrate", &self.bitrate()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for SendStats { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SendStatsRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + packet_count: ::core::convert::TryInto::try_into(value.packet_count()?)?, + byte_count: ::core::convert::TryInto::try_into(value.byte_count()?)?, + bitrate: ::core::convert::TryInto::try_into(value.bitrate()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SendStatsRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SendStatsRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SendStatsRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for SendStats { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SendStatsRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[SendStatsRef]", "read_as_root", 0) + }) + } + } + } + pub mod rtx_stream { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Params { + pub ssrc: u32, + pub payload_type: u8, + pub mime_type: ::planus::alloc::string::String, + pub clock_rate: u32, + pub rrid: ::core::option::Option<::planus::alloc::string::String>, + pub cname: ::planus::alloc::string::String, + } + + impl Params { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ssrc: impl ::planus::WriteAsDefault, + field_payload_type: impl ::planus::WriteAsDefault, + field_mime_type: impl ::planus::WriteAs<::planus::Offset>, + field_clock_rate: impl ::planus::WriteAsDefault, + field_rrid: impl ::planus::WriteAsOptional<::planus::Offset<::core::primitive::str>>, + field_cname: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_ssrc = field_ssrc.prepare(builder, &0); + + let prepared_payload_type = field_payload_type.prepare(builder, &0); + + let prepared_mime_type = field_mime_type.prepare(builder); + + let prepared_clock_rate = field_clock_rate.prepare(builder, &0); + + let prepared_rrid = field_rrid.prepare(builder); + + let prepared_cname = field_cname.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<14, 21>::new(builder); + + if prepared_ssrc.is_some() { + table_writer.calculate_size::(2); + } + if prepared_payload_type.is_some() { + table_writer.calculate_size::(4); + } + table_writer.calculate_size::<::planus::Offset>(6); + if prepared_clock_rate.is_some() { + table_writer.calculate_size::(8); + } + if prepared_rrid.is_some() { + table_writer.calculate_size::<::planus::Offset>(10); + } + table_writer.calculate_size::<::planus::Offset>(12); + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_ssrc) = prepared_ssrc { + table_writer.write::<_, _, 4>(0, &prepared_ssrc); + } + table_writer.write::<_, _, 4>(2, &prepared_mime_type); + if let ::core::option::Option::Some(prepared_clock_rate) = + prepared_clock_rate + { + table_writer.write::<_, _, 4>(3, &prepared_clock_rate); + } + if let ::core::option::Option::Some(prepared_rrid) = prepared_rrid { + table_writer.write::<_, _, 4>(4, &prepared_rrid); + } + table_writer.write::<_, _, 4>(5, &prepared_cname); + if let ::core::option::Option::Some(prepared_payload_type) = + prepared_payload_type + { + table_writer.write::<_, _, 1>(1, &prepared_payload_type); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Params { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Params { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Params { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Params::create( + builder, + &self.ssrc, + &self.payload_type, + &self.mime_type, + &self.clock_rate, + &self.rrid, + &self.cname, + ) + } + } + + #[derive(Copy, Clone)] + pub struct ParamsRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ParamsRef<'a> { + pub fn ssrc(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(0, "Params", "ssrc")?.unwrap_or(0)) + } + + pub fn payload_type(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(1, "Params", "payload_type")?.unwrap_or(0), + ) + } + + pub fn mime_type(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(2, "Params", "mime_type") + } + + pub fn clock_rate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(3, "Params", "clock_rate")?.unwrap_or(0), + ) + } + + pub fn rrid( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(4, "Params", "rrid") + } + + pub fn cname(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(5, "Params", "cname") + } + } + + impl<'a> ::core::fmt::Debug for ParamsRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ParamsRef"); + f.field("ssrc", &self.ssrc()); + f.field("payload_type", &self.payload_type()); + f.field("mime_type", &self.mime_type()); + f.field("clock_rate", &self.clock_rate()); + if let ::core::option::Option::Some(field_rrid) = self.rrid().transpose() { + f.field("rrid", &field_rrid); + } + f.field("cname", &self.cname()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Params { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ParamsRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ssrc: ::core::convert::TryInto::try_into(value.ssrc()?)?, + payload_type: ::core::convert::TryInto::try_into(value.payload_type()?)?, + mime_type: ::core::convert::TryInto::try_into(value.mime_type()?)?, + clock_rate: ::core::convert::TryInto::try_into(value.clock_rate()?)?, + rrid: if let ::core::option::Option::Some(rrid) = value.rrid()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(rrid)?) + } else { + ::core::option::Option::None + }, + cname: ::core::convert::TryInto::try_into(value.cname()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ParamsRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ParamsRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ParamsRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Params { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ParamsRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ParamsRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct RtxDump { + pub params: ::planus::alloc::boxed::Box, + } + + impl RtxDump { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_params: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_params = field_params.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_params); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RtxDump { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RtxDump { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RtxDump { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + RtxDump::create(builder, &self.params) + } + } + + #[derive(Copy, Clone)] + pub struct RtxDumpRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RtxDumpRef<'a> { + pub fn params(&self) -> ::planus::Result> { + self.0.access_required(0, "RtxDump", "params") + } + } + + impl<'a> ::core::fmt::Debug for RtxDumpRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RtxDumpRef"); + f.field("params", &self.params()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RtxDump { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RtxDumpRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + params: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.params()?)?, + ), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RtxDumpRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RtxDumpRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RtxDumpRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RtxDump { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RtxDumpRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[RtxDumpRef]", "read_as_root", 0) + }) + } + } + } + pub mod data_consumer { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct GetBufferedAmountResponse { + pub buffered_amount: u32, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for GetBufferedAmountResponse { + fn default() -> Self { + Self { buffered_amount: 0 } + } + } + + impl GetBufferedAmountResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_buffered_amount: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_buffered_amount = field_buffered_amount.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_buffered_amount.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_buffered_amount) = + prepared_buffered_amount + { + table_writer.write::<_, _, 4>(0, &prepared_buffered_amount); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for GetBufferedAmountResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for GetBufferedAmountResponse + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for GetBufferedAmountResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + GetBufferedAmountResponse::create(builder, &self.buffered_amount) + } + } + + #[derive(Copy, Clone)] + pub struct GetBufferedAmountResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> GetBufferedAmountResponseRef<'a> { + pub fn buffered_amount(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "GetBufferedAmountResponse", "buffered_amount")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for GetBufferedAmountResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("GetBufferedAmountResponseRef"); + f.field("buffered_amount", &self.buffered_amount()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for GetBufferedAmountResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: GetBufferedAmountResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + buffered_amount: ::core::convert::TryInto::try_into( + value.buffered_amount()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for GetBufferedAmountResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for GetBufferedAmountResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[GetBufferedAmountResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for GetBufferedAmountResponse + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for GetBufferedAmountResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[GetBufferedAmountResponseRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SetBufferedAmountLowThresholdRequest { + pub threshold: u32, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for SetBufferedAmountLowThresholdRequest { + fn default() -> Self { + Self { threshold: 0 } + } + } + + impl SetBufferedAmountLowThresholdRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_threshold: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_threshold = field_threshold.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_threshold.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_threshold) = prepared_threshold + { + table_writer.write::<_, _, 4>(0, &prepared_threshold); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for SetBufferedAmountLowThresholdRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for SetBufferedAmountLowThresholdRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset + for SetBufferedAmountLowThresholdRequest + { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SetBufferedAmountLowThresholdRequest::create(builder, &self.threshold) + } + } + + #[derive(Copy, Clone)] + pub struct SetBufferedAmountLowThresholdRequestRef<'a>( + ::planus::table_reader::Table<'a>, + ); + + impl<'a> SetBufferedAmountLowThresholdRequestRef<'a> { + pub fn threshold(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "SetBufferedAmountLowThresholdRequest", "threshold")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for SetBufferedAmountLowThresholdRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SetBufferedAmountLowThresholdRequestRef"); + f.field("threshold", &self.threshold()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for SetBufferedAmountLowThresholdRequest + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from( + value: SetBufferedAmountLowThresholdRequestRef<'a>, + ) -> ::planus::Result { + ::core::result::Result::Ok(Self { + threshold: ::core::convert::TryInto::try_into(value.threshold()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SetBufferedAmountLowThresholdRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SetBufferedAmountLowThresholdRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SetBufferedAmountLowThresholdRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for SetBufferedAmountLowThresholdRequest + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SetBufferedAmountLowThresholdRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[SetBufferedAmountLowThresholdRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct DumpResponse { + pub id: ::planus::alloc::string::String, + pub data_producer_id: ::planus::alloc::string::String, + pub type_: ::planus::alloc::string::String, + pub sctp_stream_parameters: ::core::option::Option< + ::planus::alloc::boxed::Box, + >, + pub label: ::planus::alloc::string::String, + pub protocol: ::planus::alloc::string::String, + } + + impl DumpResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_id: impl ::planus::WriteAs<::planus::Offset>, + field_data_producer_id: impl ::planus::WriteAs<::planus::Offset>, + field_type_: impl ::planus::WriteAs<::planus::Offset>, + field_sctp_stream_parameters: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + field_label: impl ::planus::WriteAs<::planus::Offset>, + field_protocol: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_id = field_id.prepare(builder); + + let prepared_data_producer_id = field_data_producer_id.prepare(builder); + + let prepared_type_ = field_type_.prepare(builder); + + let prepared_sctp_stream_parameters = + field_sctp_stream_parameters.prepare(builder); + + let prepared_label = field_label.prepare(builder); + + let prepared_protocol = field_protocol.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<14, 24>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + table_writer.calculate_size::<::planus::Offset>(6); + if prepared_sctp_stream_parameters.is_some() { + table_writer.calculate_size::<::planus::Offset>(8); + } + table_writer.calculate_size::<::planus::Offset>(10); + table_writer.calculate_size::<::planus::Offset>(12); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_id); + table_writer.write::<_, _, 4>(1, &prepared_data_producer_id); + table_writer.write::<_, _, 4>(2, &prepared_type_); + if let ::core::option::Option::Some(prepared_sctp_stream_parameters) = + prepared_sctp_stream_parameters + { + table_writer.write::<_, _, 4>(3, &prepared_sctp_stream_parameters); + } + table_writer.write::<_, _, 4>(4, &prepared_label); + table_writer.write::<_, _, 4>(5, &prepared_protocol); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for DumpResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + DumpResponse::create( + builder, + &self.id, + &self.data_producer_id, + &self.type_, + &self.sctp_stream_parameters, + &self.label, + &self.protocol, + ) + } + } + + #[derive(Copy, Clone)] + pub struct DumpResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DumpResponseRef<'a> { + pub fn id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "DumpResponse", "id") + } + + pub fn data_producer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(1, "DumpResponse", "data_producer_id") + } + + pub fn type_(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(2, "DumpResponse", "type_") + } + + pub fn sctp_stream_parameters( + &self, + ) -> ::planus::Result< + ::core::option::Option>, + > { + self.0.access(3, "DumpResponse", "sctp_stream_parameters") + } + + pub fn label(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(4, "DumpResponse", "label") + } + + pub fn protocol(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(5, "DumpResponse", "protocol") + } + } + + impl<'a> ::core::fmt::Debug for DumpResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DumpResponseRef"); + f.field("id", &self.id()); + f.field("data_producer_id", &self.data_producer_id()); + f.field("type_", &self.type_()); + if let ::core::option::Option::Some(field_sctp_stream_parameters) = + self.sctp_stream_parameters().transpose() + { + f.field("sctp_stream_parameters", &field_sctp_stream_parameters); + } + f.field("label", &self.label()); + f.field("protocol", &self.protocol()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for DumpResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DumpResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + id: ::core::convert::TryInto::try_into(value.id()?)?, + data_producer_id: ::core::convert::TryInto::try_into( + value.data_producer_id()?, + )?, + type_: ::core::convert::TryInto::try_into(value.type_()?)?, + sctp_stream_parameters: if let ::core::option::Option::Some( + sctp_stream_parameters, + ) = value.sctp_stream_parameters()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(sctp_stream_parameters)?, + )) + } else { + ::core::option::Option::None + }, + label: ::core::convert::TryInto::try_into(value.label()?)?, + protocol: ::core::convert::TryInto::try_into(value.protocol()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DumpResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DumpResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DumpResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for DumpResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DumpResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[DumpResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct GetStatsResponse { + pub timestamp: u64, + pub label: ::planus::alloc::string::String, + pub protocol: ::planus::alloc::string::String, + pub messages_sent: u64, + pub bytes_sent: u64, + pub buffered_amount: u32, + } + + impl GetStatsResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_timestamp: impl ::planus::WriteAsDefault, + field_label: impl ::planus::WriteAs<::planus::Offset>, + field_protocol: impl ::planus::WriteAs<::planus::Offset>, + field_messages_sent: impl ::planus::WriteAsDefault, + field_bytes_sent: impl ::planus::WriteAsDefault, + field_buffered_amount: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_timestamp = field_timestamp.prepare(builder, &0); + + let prepared_label = field_label.prepare(builder); + + let prepared_protocol = field_protocol.prepare(builder); + + let prepared_messages_sent = field_messages_sent.prepare(builder, &0); + + let prepared_bytes_sent = field_bytes_sent.prepare(builder, &0); + + let prepared_buffered_amount = field_buffered_amount.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<14, 36>::new(builder); + + if prepared_timestamp.is_some() { + table_writer.calculate_size::(2); + } + table_writer.calculate_size::<::planus::Offset>(4); + table_writer.calculate_size::<::planus::Offset>(6); + if prepared_messages_sent.is_some() { + table_writer.calculate_size::(8); + } + if prepared_bytes_sent.is_some() { + table_writer.calculate_size::(10); + } + if prepared_buffered_amount.is_some() { + table_writer.calculate_size::(12); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_timestamp) = prepared_timestamp + { + table_writer.write::<_, _, 8>(0, &prepared_timestamp); + } + if let ::core::option::Option::Some(prepared_messages_sent) = + prepared_messages_sent + { + table_writer.write::<_, _, 8>(3, &prepared_messages_sent); + } + if let ::core::option::Option::Some(prepared_bytes_sent) = + prepared_bytes_sent + { + table_writer.write::<_, _, 8>(4, &prepared_bytes_sent); + } + table_writer.write::<_, _, 4>(1, &prepared_label); + table_writer.write::<_, _, 4>(2, &prepared_protocol); + if let ::core::option::Option::Some(prepared_buffered_amount) = + prepared_buffered_amount + { + table_writer.write::<_, _, 4>(5, &prepared_buffered_amount); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for GetStatsResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + GetStatsResponse::create( + builder, + &self.timestamp, + &self.label, + &self.protocol, + &self.messages_sent, + &self.bytes_sent, + &self.buffered_amount, + ) + } + } + + #[derive(Copy, Clone)] + pub struct GetStatsResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> GetStatsResponseRef<'a> { + pub fn timestamp(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "GetStatsResponse", "timestamp")? + .unwrap_or(0), + ) + } + + pub fn label(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "GetStatsResponse", "label") + } + + pub fn protocol(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(2, "GetStatsResponse", "protocol") + } + + pub fn messages_sent(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(3, "GetStatsResponse", "messages_sent")? + .unwrap_or(0), + ) + } + + pub fn bytes_sent(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(4, "GetStatsResponse", "bytes_sent")? + .unwrap_or(0), + ) + } + + pub fn buffered_amount(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(5, "GetStatsResponse", "buffered_amount")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for GetStatsResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("GetStatsResponseRef"); + f.field("timestamp", &self.timestamp()); + f.field("label", &self.label()); + f.field("protocol", &self.protocol()); + f.field("messages_sent", &self.messages_sent()); + f.field("bytes_sent", &self.bytes_sent()); + f.field("buffered_amount", &self.buffered_amount()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for GetStatsResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: GetStatsResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + timestamp: ::core::convert::TryInto::try_into(value.timestamp()?)?, + label: ::core::convert::TryInto::try_into(value.label()?)?, + protocol: ::core::convert::TryInto::try_into(value.protocol()?)?, + messages_sent: ::core::convert::TryInto::try_into(value.messages_sent()?)?, + bytes_sent: ::core::convert::TryInto::try_into(value.bytes_sent()?)?, + buffered_amount: ::core::convert::TryInto::try_into( + value.buffered_amount()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for GetStatsResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for GetStatsResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[GetStatsResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for GetStatsResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for GetStatsResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[GetStatsResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct String { + pub value: ::planus::alloc::string::String, + } + + impl String { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_value: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_value = field_value.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_value); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for String { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for String { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for String { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + String::create(builder, &self.value) + } + } + + #[derive(Copy, Clone)] + pub struct StringRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> StringRef<'a> { + pub fn value(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "String", "value") + } + } + + impl<'a> ::core::fmt::Debug for StringRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("StringRef"); + f.field("value", &self.value()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for String { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: StringRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + value: ::core::convert::TryInto::try_into(value.value()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for StringRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for StringRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[StringRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for String { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for StringRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[StringRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Binary { + pub value: ::planus::alloc::vec::Vec, + } + + impl Binary { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_value: impl ::planus::WriteAs<::planus::Offset<[u8]>>, + ) -> ::planus::Offset { + let prepared_value = field_value.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset<[u8]>>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_value); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Binary { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Binary { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Binary { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Binary::create(builder, &self.value) + } + } + + #[derive(Copy, Clone)] + pub struct BinaryRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> BinaryRef<'a> { + pub fn value(&self) -> ::planus::Result<::planus::Vector<'a, u8>> { + self.0.access_required(0, "Binary", "value") + } + } + + impl<'a> ::core::fmt::Debug for BinaryRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("BinaryRef"); + f.field("value", &self.value()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Binary { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: BinaryRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + value: value.value()?.to_vec()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for BinaryRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for BinaryRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[BinaryRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Binary { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for BinaryRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[BinaryRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub enum Data { + String(::planus::alloc::boxed::Box), + Binary(::planus::alloc::boxed::Box), + } + + impl Data { + pub fn create_string( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(1, value.prepare(builder).downcast()) + } + + pub fn create_binary( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(2, value.prepare(builder).downcast()) + } + } + + impl ::planus::WriteAsUnion for Data { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::UnionOffset { + match self { + Self::String(value) => Self::create_string(builder, value), + Self::Binary(value) => Self::create_binary(builder, value), + } + } + } + + impl ::planus::WriteAsOptionalUnion for Data { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::UnionOffset> { + ::core::option::Option::Some(::planus::WriteAsUnion::prepare(self, builder)) + } + } + + #[derive(Copy, Clone, Debug)] + pub enum DataRef<'a> { + String(self::StringRef<'a>), + Binary(self::BinaryRef<'a>), + } + + impl<'a> ::core::convert::TryFrom> for Data { + type Error = ::planus::Error; + + fn try_from(value: DataRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(match value { + DataRef::String(value) => Data::String(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )), + + DataRef::Binary(value) => Data::Binary(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )), + }) + } + } + + impl<'a> ::planus::TableReadUnion<'a> for DataRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + field_offset: usize, + tag: u8, + ) -> ::core::result::Result { + match tag { + 1 => ::core::result::Result::Ok(Self::String( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 2 => ::core::result::Result::Ok(Self::Binary( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + _ => ::core::result::Result::Err( + ::planus::errors::ErrorKind::UnknownUnionTag { tag }, + ), + } + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SendRequest { + pub ppid: u8, + pub data: self::Data, + } + + impl SendRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ppid: impl ::planus::WriteAsDefault, + field_data: impl ::planus::WriteAsUnion, + ) -> ::planus::Offset { + let prepared_ppid = field_ppid.prepare(builder, &0); + + let prepared_data = field_data.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 6>::new(builder); + + if prepared_ppid.is_some() { + table_writer.calculate_size::(2); + } + table_writer.calculate_size::(4); + table_writer.calculate_size::<::planus::Offset>(6); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(2, &prepared_data.offset()); + if let ::core::option::Option::Some(prepared_ppid) = prepared_ppid { + table_writer.write::<_, _, 1>(0, &prepared_ppid); + } + table_writer.write::<_, _, 1>(1, &prepared_data.tag()); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for SendRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for SendRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SendRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SendRequest::create(builder, &self.ppid, &self.data) + } + } + + #[derive(Copy, Clone)] + pub struct SendRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SendRequestRef<'a> { + pub fn ppid(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "SendRequest", "ppid")?.unwrap_or(0), + ) + } + + pub fn data(&self) -> ::planus::Result> { + self.0.access_union_required(1, "SendRequest", "data") + } + } + + impl<'a> ::core::fmt::Debug for SendRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SendRequestRef"); + f.field("ppid", &self.ppid()); + f.field("data", &self.data()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for SendRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SendRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ppid: ::core::convert::TryInto::try_into(value.ppid()?)?, + data: ::core::convert::TryInto::try_into(value.data()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SendRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SendRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SendRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for SendRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SendRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[SendRequestRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct BufferedAmountLowNotification { + pub buffered_amount: u32, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for BufferedAmountLowNotification { + fn default() -> Self { + Self { buffered_amount: 0 } + } + } + + impl BufferedAmountLowNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_buffered_amount: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_buffered_amount = field_buffered_amount.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_buffered_amount.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_buffered_amount) = + prepared_buffered_amount + { + table_writer.write::<_, _, 4>(0, &prepared_buffered_amount); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for BufferedAmountLowNotification + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for BufferedAmountLowNotification + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for BufferedAmountLowNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + BufferedAmountLowNotification::create(builder, &self.buffered_amount) + } + } + + #[derive(Copy, Clone)] + pub struct BufferedAmountLowNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> BufferedAmountLowNotificationRef<'a> { + pub fn buffered_amount(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "BufferedAmountLowNotification", "buffered_amount")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for BufferedAmountLowNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("BufferedAmountLowNotificationRef"); + f.field("buffered_amount", &self.buffered_amount()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for BufferedAmountLowNotification + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: BufferedAmountLowNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + buffered_amount: ::core::convert::TryInto::try_into( + value.buffered_amount()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for BufferedAmountLowNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for BufferedAmountLowNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[BufferedAmountLowNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for BufferedAmountLowNotification + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for BufferedAmountLowNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[BufferedAmountLowNotificationRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct MessageNotification { + pub ppid: u32, + pub data: ::planus::alloc::vec::Vec, + } + + impl MessageNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ppid: impl ::planus::WriteAsDefault, + field_data: impl ::planus::WriteAs<::planus::Offset<[u8]>>, + ) -> ::planus::Offset { + let prepared_ppid = field_ppid.prepare(builder, &0); + + let prepared_data = field_data.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + if prepared_ppid.is_some() { + table_writer.calculate_size::(2); + } + table_writer.calculate_size::<::planus::Offset<[u8]>>(4); + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_ppid) = prepared_ppid { + table_writer.write::<_, _, 4>(0, &prepared_ppid); + } + table_writer.write::<_, _, 4>(1, &prepared_data); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for MessageNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for MessageNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for MessageNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + MessageNotification::create(builder, &self.ppid, &self.data) + } + } + + #[derive(Copy, Clone)] + pub struct MessageNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> MessageNotificationRef<'a> { + pub fn ppid(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "MessageNotification", "ppid")? + .unwrap_or(0), + ) + } + + pub fn data(&self) -> ::planus::Result<::planus::Vector<'a, u8>> { + self.0.access_required(1, "MessageNotification", "data") + } + } + + impl<'a> ::core::fmt::Debug for MessageNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("MessageNotificationRef"); + f.field("ppid", &self.ppid()); + f.field("data", &self.data()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for MessageNotification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: MessageNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ppid: ::core::convert::TryInto::try_into(value.ppid()?)?, + data: value.data()?.to_vec()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for MessageNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for MessageNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[MessageNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for MessageNotification { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for MessageNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[MessageNotificationRef]", + "read_as_root", + 0, + ) + }) + } + } + } + pub mod sctp_parameters { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct NumSctpStreams { + pub os: u32, + pub mis: u32, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for NumSctpStreams { + fn default() -> Self { + Self { + os: 1024, + mis: 1024, + } + } + } + + impl NumSctpStreams { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_os: impl ::planus::WriteAsDefault, + field_mis: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_os = field_os.prepare(builder, &1024); + + let prepared_mis = field_mis.prepare(builder, &1024); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + if prepared_os.is_some() { + table_writer.calculate_size::(2); + } + if prepared_mis.is_some() { + table_writer.calculate_size::(4); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_os) = prepared_os { + table_writer.write::<_, _, 4>(0, &prepared_os); + } + if let ::core::option::Option::Some(prepared_mis) = prepared_mis { + table_writer.write::<_, _, 4>(1, &prepared_mis); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for NumSctpStreams { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for NumSctpStreams { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for NumSctpStreams { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + NumSctpStreams::create(builder, &self.os, &self.mis) + } + } + + #[derive(Copy, Clone)] + pub struct NumSctpStreamsRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> NumSctpStreamsRef<'a> { + pub fn os(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "NumSctpStreams", "os")?.unwrap_or(1024), + ) + } + + pub fn mis(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(1, "NumSctpStreams", "mis")?.unwrap_or(1024), + ) + } + } + + impl<'a> ::core::fmt::Debug for NumSctpStreamsRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("NumSctpStreamsRef"); + f.field("os", &self.os()); + f.field("mis", &self.mis()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for NumSctpStreams { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: NumSctpStreamsRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + os: ::core::convert::TryInto::try_into(value.os()?)?, + mis: ::core::convert::TryInto::try_into(value.mis()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for NumSctpStreamsRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for NumSctpStreamsRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[NumSctpStreamsRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for NumSctpStreams { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for NumSctpStreamsRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[NumSctpStreamsRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SctpParameters { + pub port: u16, + pub os: u16, + pub mis: u16, + pub max_message_size: u32, + pub send_buffer_size: u32, + pub sctp_buffered_amount: u32, + pub is_data_channel: bool, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for SctpParameters { + fn default() -> Self { + Self { + port: 5000, + os: 0, + mis: 0, + max_message_size: 0, + send_buffer_size: 0, + sctp_buffered_amount: 0, + is_data_channel: false, + } + } + } + + impl SctpParameters { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_port: impl ::planus::WriteAsDefault, + field_os: impl ::planus::WriteAsDefault, + field_mis: impl ::planus::WriteAsDefault, + field_max_message_size: impl ::planus::WriteAsDefault, + field_send_buffer_size: impl ::planus::WriteAsDefault, + field_sctp_buffered_amount: impl ::planus::WriteAsDefault, + field_is_data_channel: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_port = field_port.prepare(builder, &5000); + + let prepared_os = field_os.prepare(builder, &0); + + let prepared_mis = field_mis.prepare(builder, &0); + + let prepared_max_message_size = field_max_message_size.prepare(builder, &0); + + let prepared_send_buffer_size = field_send_buffer_size.prepare(builder, &0); + + let prepared_sctp_buffered_amount = + field_sctp_buffered_amount.prepare(builder, &0); + + let prepared_is_data_channel = field_is_data_channel.prepare(builder, &false); + + let mut table_writer = + ::planus::table_writer::TableWriter::<16, 19>::new(builder); + + if prepared_port.is_some() { + table_writer.calculate_size::(2); + } + if prepared_os.is_some() { + table_writer.calculate_size::(4); + } + if prepared_mis.is_some() { + table_writer.calculate_size::(6); + } + if prepared_max_message_size.is_some() { + table_writer.calculate_size::(8); + } + if prepared_send_buffer_size.is_some() { + table_writer.calculate_size::(10); + } + if prepared_sctp_buffered_amount.is_some() { + table_writer.calculate_size::(12); + } + if prepared_is_data_channel.is_some() { + table_writer.calculate_size::(14); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_max_message_size) = + prepared_max_message_size + { + table_writer.write::<_, _, 4>(3, &prepared_max_message_size); + } + if let ::core::option::Option::Some(prepared_send_buffer_size) = + prepared_send_buffer_size + { + table_writer.write::<_, _, 4>(4, &prepared_send_buffer_size); + } + if let ::core::option::Option::Some(prepared_sctp_buffered_amount) = + prepared_sctp_buffered_amount + { + table_writer.write::<_, _, 4>(5, &prepared_sctp_buffered_amount); + } + if let ::core::option::Option::Some(prepared_port) = prepared_port { + table_writer.write::<_, _, 2>(0, &prepared_port); + } + if let ::core::option::Option::Some(prepared_os) = prepared_os { + table_writer.write::<_, _, 2>(1, &prepared_os); + } + if let ::core::option::Option::Some(prepared_mis) = prepared_mis { + table_writer.write::<_, _, 2>(2, &prepared_mis); + } + if let ::core::option::Option::Some(prepared_is_data_channel) = + prepared_is_data_channel + { + table_writer.write::<_, _, 1>(6, &prepared_is_data_channel); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for SctpParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for SctpParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SctpParameters { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SctpParameters::create( + builder, + &self.port, + &self.os, + &self.mis, + &self.max_message_size, + &self.send_buffer_size, + &self.sctp_buffered_amount, + &self.is_data_channel, + ) + } + } + + #[derive(Copy, Clone)] + pub struct SctpParametersRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SctpParametersRef<'a> { + pub fn port(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "SctpParameters", "port")?.unwrap_or(5000), + ) + } + + pub fn os(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(1, "SctpParameters", "os")?.unwrap_or(0), + ) + } + + pub fn mis(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(2, "SctpParameters", "mis")?.unwrap_or(0), + ) + } + + pub fn max_message_size(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(3, "SctpParameters", "max_message_size")? + .unwrap_or(0), + ) + } + + pub fn send_buffer_size(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(4, "SctpParameters", "send_buffer_size")? + .unwrap_or(0), + ) + } + + pub fn sctp_buffered_amount(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(5, "SctpParameters", "sctp_buffered_amount")? + .unwrap_or(0), + ) + } + + pub fn is_data_channel(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(6, "SctpParameters", "is_data_channel")? + .unwrap_or(false), + ) + } + } + + impl<'a> ::core::fmt::Debug for SctpParametersRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SctpParametersRef"); + f.field("port", &self.port()); + f.field("os", &self.os()); + f.field("mis", &self.mis()); + f.field("max_message_size", &self.max_message_size()); + f.field("send_buffer_size", &self.send_buffer_size()); + f.field("sctp_buffered_amount", &self.sctp_buffered_amount()); + f.field("is_data_channel", &self.is_data_channel()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for SctpParameters { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SctpParametersRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + port: ::core::convert::TryInto::try_into(value.port()?)?, + os: ::core::convert::TryInto::try_into(value.os()?)?, + mis: ::core::convert::TryInto::try_into(value.mis()?)?, + max_message_size: ::core::convert::TryInto::try_into( + value.max_message_size()?, + )?, + send_buffer_size: ::core::convert::TryInto::try_into( + value.send_buffer_size()?, + )?, + sctp_buffered_amount: ::core::convert::TryInto::try_into( + value.sctp_buffered_amount()?, + )?, + is_data_channel: ::core::convert::TryInto::try_into( + value.is_data_channel()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SctpParametersRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SctpParametersRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SctpParametersRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for SctpParameters { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SctpParametersRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[SctpParametersRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SctpStreamParameters { + pub stream_id: u16, + pub ordered: ::core::option::Option, + pub max_packet_life_time: ::core::option::Option, + pub max_retransmits: ::core::option::Option, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for SctpStreamParameters { + fn default() -> Self { + Self { + stream_id: 0, + ordered: ::core::default::Default::default(), + max_packet_life_time: ::core::default::Default::default(), + max_retransmits: ::core::default::Default::default(), + } + } + } + + impl SctpStreamParameters { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_stream_id: impl ::planus::WriteAsDefault, + field_ordered: impl ::planus::WriteAsOptional, + field_max_packet_life_time: impl ::planus::WriteAsOptional, + field_max_retransmits: impl ::planus::WriteAsOptional, + ) -> ::planus::Offset { + let prepared_stream_id = field_stream_id.prepare(builder, &0); + + let prepared_ordered = field_ordered.prepare(builder); + + let prepared_max_packet_life_time = field_max_packet_life_time.prepare(builder); + + let prepared_max_retransmits = field_max_retransmits.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<10, 7>::new(builder); + + if prepared_stream_id.is_some() { + table_writer.calculate_size::(2); + } + if prepared_ordered.is_some() { + table_writer.calculate_size::(4); + } + if prepared_max_packet_life_time.is_some() { + table_writer.calculate_size::(6); + } + if prepared_max_retransmits.is_some() { + table_writer.calculate_size::(8); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_stream_id) = prepared_stream_id + { + table_writer.write::<_, _, 2>(0, &prepared_stream_id); + } + if let ::core::option::Option::Some(prepared_max_packet_life_time) = + prepared_max_packet_life_time + { + table_writer.write::<_, _, 2>(2, &prepared_max_packet_life_time); + } + if let ::core::option::Option::Some(prepared_max_retransmits) = + prepared_max_retransmits + { + table_writer.write::<_, _, 2>(3, &prepared_max_retransmits); + } + if let ::core::option::Option::Some(prepared_ordered) = prepared_ordered { + table_writer.write::<_, _, 1>(1, &prepared_ordered); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for SctpStreamParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for SctpStreamParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SctpStreamParameters { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SctpStreamParameters::create( + builder, + &self.stream_id, + &self.ordered, + &self.max_packet_life_time, + &self.max_retransmits, + ) + } + } + + #[derive(Copy, Clone)] + pub struct SctpStreamParametersRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SctpStreamParametersRef<'a> { + pub fn stream_id(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "SctpStreamParameters", "stream_id")? + .unwrap_or(0), + ) + } + + pub fn ordered(&self) -> ::planus::Result<::core::option::Option> { + self.0.access(1, "SctpStreamParameters", "ordered") + } + + pub fn max_packet_life_time( + &self, + ) -> ::planus::Result<::core::option::Option> { + self.0 + .access(2, "SctpStreamParameters", "max_packet_life_time") + } + + pub fn max_retransmits(&self) -> ::planus::Result<::core::option::Option> { + self.0.access(3, "SctpStreamParameters", "max_retransmits") + } + } + + impl<'a> ::core::fmt::Debug for SctpStreamParametersRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SctpStreamParametersRef"); + f.field("stream_id", &self.stream_id()); + if let ::core::option::Option::Some(field_ordered) = self.ordered().transpose() + { + f.field("ordered", &field_ordered); + } + if let ::core::option::Option::Some(field_max_packet_life_time) = + self.max_packet_life_time().transpose() + { + f.field("max_packet_life_time", &field_max_packet_life_time); + } + if let ::core::option::Option::Some(field_max_retransmits) = + self.max_retransmits().transpose() + { + f.field("max_retransmits", &field_max_retransmits); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for SctpStreamParameters { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SctpStreamParametersRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + stream_id: ::core::convert::TryInto::try_into(value.stream_id()?)?, + ordered: if let ::core::option::Option::Some(ordered) = value.ordered()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + ordered, + )?) + } else { + ::core::option::Option::None + }, + max_packet_life_time: if let ::core::option::Option::Some( + max_packet_life_time, + ) = value.max_packet_life_time()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + max_packet_life_time, + )?) + } else { + ::core::option::Option::None + }, + max_retransmits: if let ::core::option::Option::Some(max_retransmits) = + value.max_retransmits()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + max_retransmits, + )?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SctpStreamParametersRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SctpStreamParametersRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SctpStreamParametersRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for SctpStreamParameters { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SctpStreamParametersRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[SctpStreamParametersRef]", + "read_as_root", + 0, + ) + }) + } + } + } + pub mod data_producer { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct DumpResponse { + pub id: ::planus::alloc::string::String, + pub type_: ::planus::alloc::string::String, + pub sctp_stream_parameters: ::core::option::Option< + ::planus::alloc::boxed::Box, + >, + pub label: ::planus::alloc::string::String, + pub protocol: ::planus::alloc::string::String, + } + + impl DumpResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_id: impl ::planus::WriteAs<::planus::Offset>, + field_type_: impl ::planus::WriteAs<::planus::Offset>, + field_sctp_stream_parameters: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + field_label: impl ::planus::WriteAs<::planus::Offset>, + field_protocol: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_id = field_id.prepare(builder); + + let prepared_type_ = field_type_.prepare(builder); + + let prepared_sctp_stream_parameters = + field_sctp_stream_parameters.prepare(builder); + + let prepared_label = field_label.prepare(builder); + + let prepared_protocol = field_protocol.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<12, 20>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + if prepared_sctp_stream_parameters.is_some() { + table_writer.calculate_size::<::planus::Offset>(6); + } + table_writer.calculate_size::<::planus::Offset>(8); + table_writer.calculate_size::<::planus::Offset>(10); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_id); + table_writer.write::<_, _, 4>(1, &prepared_type_); + if let ::core::option::Option::Some(prepared_sctp_stream_parameters) = + prepared_sctp_stream_parameters + { + table_writer.write::<_, _, 4>(2, &prepared_sctp_stream_parameters); + } + table_writer.write::<_, _, 4>(3, &prepared_label); + table_writer.write::<_, _, 4>(4, &prepared_protocol); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for DumpResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + DumpResponse::create( + builder, + &self.id, + &self.type_, + &self.sctp_stream_parameters, + &self.label, + &self.protocol, + ) + } + } + + #[derive(Copy, Clone)] + pub struct DumpResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DumpResponseRef<'a> { + pub fn id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "DumpResponse", "id") + } + + pub fn type_(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "DumpResponse", "type_") + } + + pub fn sctp_stream_parameters( + &self, + ) -> ::planus::Result< + ::core::option::Option>, + > { + self.0.access(2, "DumpResponse", "sctp_stream_parameters") + } + + pub fn label(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(3, "DumpResponse", "label") + } + + pub fn protocol(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(4, "DumpResponse", "protocol") + } + } + + impl<'a> ::core::fmt::Debug for DumpResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DumpResponseRef"); + f.field("id", &self.id()); + f.field("type_", &self.type_()); + if let ::core::option::Option::Some(field_sctp_stream_parameters) = + self.sctp_stream_parameters().transpose() + { + f.field("sctp_stream_parameters", &field_sctp_stream_parameters); + } + f.field("label", &self.label()); + f.field("protocol", &self.protocol()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for DumpResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DumpResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + id: ::core::convert::TryInto::try_into(value.id()?)?, + type_: ::core::convert::TryInto::try_into(value.type_()?)?, + sctp_stream_parameters: if let ::core::option::Option::Some( + sctp_stream_parameters, + ) = value.sctp_stream_parameters()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(sctp_stream_parameters)?, + )) + } else { + ::core::option::Option::None + }, + label: ::core::convert::TryInto::try_into(value.label()?)?, + protocol: ::core::convert::TryInto::try_into(value.protocol()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DumpResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DumpResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DumpResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for DumpResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DumpResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[DumpResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct GetStatsResponse { + pub timestamp: u64, + pub label: ::planus::alloc::string::String, + pub protocol: ::planus::alloc::string::String, + pub messages_received: u64, + pub bytes_received: u64, + pub buffered_amount: u32, + } + + impl GetStatsResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_timestamp: impl ::planus::WriteAsDefault, + field_label: impl ::planus::WriteAs<::planus::Offset>, + field_protocol: impl ::planus::WriteAs<::planus::Offset>, + field_messages_received: impl ::planus::WriteAsDefault, + field_bytes_received: impl ::planus::WriteAsDefault, + field_buffered_amount: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_timestamp = field_timestamp.prepare(builder, &0); + + let prepared_label = field_label.prepare(builder); + + let prepared_protocol = field_protocol.prepare(builder); + + let prepared_messages_received = field_messages_received.prepare(builder, &0); + + let prepared_bytes_received = field_bytes_received.prepare(builder, &0); + + let prepared_buffered_amount = field_buffered_amount.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<14, 36>::new(builder); + + if prepared_timestamp.is_some() { + table_writer.calculate_size::(2); + } + table_writer.calculate_size::<::planus::Offset>(4); + table_writer.calculate_size::<::planus::Offset>(6); + if prepared_messages_received.is_some() { + table_writer.calculate_size::(8); + } + if prepared_bytes_received.is_some() { + table_writer.calculate_size::(10); + } + if prepared_buffered_amount.is_some() { + table_writer.calculate_size::(12); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_timestamp) = prepared_timestamp + { + table_writer.write::<_, _, 8>(0, &prepared_timestamp); + } + if let ::core::option::Option::Some(prepared_messages_received) = + prepared_messages_received + { + table_writer.write::<_, _, 8>(3, &prepared_messages_received); + } + if let ::core::option::Option::Some(prepared_bytes_received) = + prepared_bytes_received + { + table_writer.write::<_, _, 8>(4, &prepared_bytes_received); + } + table_writer.write::<_, _, 4>(1, &prepared_label); + table_writer.write::<_, _, 4>(2, &prepared_protocol); + if let ::core::option::Option::Some(prepared_buffered_amount) = + prepared_buffered_amount + { + table_writer.write::<_, _, 4>(5, &prepared_buffered_amount); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for GetStatsResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + GetStatsResponse::create( + builder, + &self.timestamp, + &self.label, + &self.protocol, + &self.messages_received, + &self.bytes_received, + &self.buffered_amount, + ) + } + } + + #[derive(Copy, Clone)] + pub struct GetStatsResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> GetStatsResponseRef<'a> { + pub fn timestamp(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "GetStatsResponse", "timestamp")? + .unwrap_or(0), + ) + } + + pub fn label(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "GetStatsResponse", "label") + } + + pub fn protocol(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(2, "GetStatsResponse", "protocol") + } + + pub fn messages_received(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(3, "GetStatsResponse", "messages_received")? + .unwrap_or(0), + ) + } + + pub fn bytes_received(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(4, "GetStatsResponse", "bytes_received")? + .unwrap_or(0), + ) + } + + pub fn buffered_amount(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(5, "GetStatsResponse", "buffered_amount")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for GetStatsResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("GetStatsResponseRef"); + f.field("timestamp", &self.timestamp()); + f.field("label", &self.label()); + f.field("protocol", &self.protocol()); + f.field("messages_received", &self.messages_received()); + f.field("bytes_received", &self.bytes_received()); + f.field("buffered_amount", &self.buffered_amount()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for GetStatsResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: GetStatsResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + timestamp: ::core::convert::TryInto::try_into(value.timestamp()?)?, + label: ::core::convert::TryInto::try_into(value.label()?)?, + protocol: ::core::convert::TryInto::try_into(value.protocol()?)?, + messages_received: ::core::convert::TryInto::try_into( + value.messages_received()?, + )?, + bytes_received: ::core::convert::TryInto::try_into( + value.bytes_received()?, + )?, + buffered_amount: ::core::convert::TryInto::try_into( + value.buffered_amount()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for GetStatsResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for GetStatsResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[GetStatsResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for GetStatsResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for GetStatsResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[GetStatsResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct String { + pub value: ::planus::alloc::string::String, + } + + impl String { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_value: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_value = field_value.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_value); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for String { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for String { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for String { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + String::create(builder, &self.value) + } + } + + #[derive(Copy, Clone)] + pub struct StringRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> StringRef<'a> { + pub fn value(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "String", "value") + } + } + + impl<'a> ::core::fmt::Debug for StringRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("StringRef"); + f.field("value", &self.value()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for String { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: StringRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + value: ::core::convert::TryInto::try_into(value.value()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for StringRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for StringRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[StringRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for String { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for StringRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[StringRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Binary { + pub value: ::planus::alloc::vec::Vec, + } + + impl Binary { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_value: impl ::planus::WriteAs<::planus::Offset<[u8]>>, + ) -> ::planus::Offset { + let prepared_value = field_value.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset<[u8]>>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_value); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Binary { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Binary { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Binary { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Binary::create(builder, &self.value) + } + } + + #[derive(Copy, Clone)] + pub struct BinaryRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> BinaryRef<'a> { + pub fn value(&self) -> ::planus::Result<::planus::Vector<'a, u8>> { + self.0.access_required(0, "Binary", "value") + } + } + + impl<'a> ::core::fmt::Debug for BinaryRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("BinaryRef"); + f.field("value", &self.value()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Binary { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: BinaryRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + value: value.value()?.to_vec()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for BinaryRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for BinaryRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[BinaryRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Binary { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for BinaryRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[BinaryRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub enum Data { + String(::planus::alloc::boxed::Box), + Binary(::planus::alloc::boxed::Box), + } + + impl Data { + pub fn create_string( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(1, value.prepare(builder).downcast()) + } + + pub fn create_binary( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(2, value.prepare(builder).downcast()) + } + } + + impl ::planus::WriteAsUnion for Data { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::UnionOffset { + match self { + Self::String(value) => Self::create_string(builder, value), + Self::Binary(value) => Self::create_binary(builder, value), + } + } + } + + impl ::planus::WriteAsOptionalUnion for Data { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::UnionOffset> { + ::core::option::Option::Some(::planus::WriteAsUnion::prepare(self, builder)) + } + } + + #[derive(Copy, Clone, Debug)] + pub enum DataRef<'a> { + String(self::StringRef<'a>), + Binary(self::BinaryRef<'a>), + } + + impl<'a> ::core::convert::TryFrom> for Data { + type Error = ::planus::Error; + + fn try_from(value: DataRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(match value { + DataRef::String(value) => Data::String(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )), + + DataRef::Binary(value) => Data::Binary(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )), + }) + } + } + + impl<'a> ::planus::TableReadUnion<'a> for DataRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + field_offset: usize, + tag: u8, + ) -> ::core::result::Result { + match tag { + 1 => ::core::result::Result::Ok(Self::String( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 2 => ::core::result::Result::Ok(Self::Binary( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + _ => ::core::result::Result::Err( + ::planus::errors::ErrorKind::UnknownUnionTag { tag }, + ), + } + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SendNotification { + pub ppid: u8, + pub data: self::Data, + } + + impl SendNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ppid: impl ::planus::WriteAsDefault, + field_data: impl ::planus::WriteAsUnion, + ) -> ::planus::Offset { + let prepared_ppid = field_ppid.prepare(builder, &0); + + let prepared_data = field_data.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 6>::new(builder); + + if prepared_ppid.is_some() { + table_writer.calculate_size::(2); + } + table_writer.calculate_size::(4); + table_writer.calculate_size::<::planus::Offset>(6); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(2, &prepared_data.offset()); + if let ::core::option::Option::Some(prepared_ppid) = prepared_ppid { + table_writer.write::<_, _, 1>(0, &prepared_ppid); + } + table_writer.write::<_, _, 1>(1, &prepared_data.tag()); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for SendNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for SendNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SendNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SendNotification::create(builder, &self.ppid, &self.data) + } + } + + #[derive(Copy, Clone)] + pub struct SendNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SendNotificationRef<'a> { + pub fn ppid(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "SendNotification", "ppid")?.unwrap_or(0), + ) + } + + pub fn data(&self) -> ::planus::Result> { + self.0.access_union_required(1, "SendNotification", "data") + } + } + + impl<'a> ::core::fmt::Debug for SendNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SendNotificationRef"); + f.field("ppid", &self.ppid()); + f.field("data", &self.data()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for SendNotification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SendNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ppid: ::core::convert::TryInto::try_into(value.ppid()?)?, + data: ::core::convert::TryInto::try_into(value.data()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SendNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SendNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SendNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for SendNotification { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SendNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[SendNotificationRef]", "read_as_root", 0) + }) + } + } + } + pub mod direct_transport { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct DirectTransportOptions { + pub base: ::planus::alloc::boxed::Box, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for DirectTransportOptions { + fn default() -> Self { + Self { + base: ::core::default::Default::default(), + } + } + } + + impl DirectTransportOptions { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_base); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for DirectTransportOptions { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for DirectTransportOptions + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for DirectTransportOptions { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + DirectTransportOptions::create(builder, &self.base) + } + } + + #[derive(Copy, Clone)] + pub struct DirectTransportOptionsRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DirectTransportOptionsRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "DirectTransportOptions", "base") + } + } + + impl<'a> ::core::fmt::Debug for DirectTransportOptionsRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DirectTransportOptionsRef"); + f.field("base", &self.base()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for DirectTransportOptions { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DirectTransportOptionsRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DirectTransportOptionsRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DirectTransportOptionsRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DirectTransportOptionsRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for DirectTransportOptions { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DirectTransportOptionsRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[DirectTransportOptionsRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct DumpResponse { + pub base: ::planus::alloc::boxed::Box, + } + + impl DumpResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_base); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for DumpResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + DumpResponse::create(builder, &self.base) + } + } + + #[derive(Copy, Clone)] + pub struct DumpResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DumpResponseRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "DumpResponse", "base") + } + } + + impl<'a> ::core::fmt::Debug for DumpResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DumpResponseRef"); + f.field("base", &self.base()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for DumpResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DumpResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DumpResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DumpResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DumpResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for DumpResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DumpResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[DumpResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct GetStatsResponse { + pub base: ::planus::alloc::boxed::Box, + } + + impl GetStatsResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_base); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for GetStatsResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + GetStatsResponse::create(builder, &self.base) + } + } + + #[derive(Copy, Clone)] + pub struct GetStatsResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> GetStatsResponseRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "GetStatsResponse", "base") + } + } + + impl<'a> ::core::fmt::Debug for GetStatsResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("GetStatsResponseRef"); + f.field("base", &self.base()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for GetStatsResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: GetStatsResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for GetStatsResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for GetStatsResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[GetStatsResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for GetStatsResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for GetStatsResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[GetStatsResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct RtcpNotification { + pub data: ::planus::alloc::vec::Vec, + } + + impl RtcpNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_data: impl ::planus::WriteAs<::planus::Offset<[u8]>>, + ) -> ::planus::Offset { + let prepared_data = field_data.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset<[u8]>>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_data); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RtcpNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RtcpNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RtcpNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + RtcpNotification::create(builder, &self.data) + } + } + + #[derive(Copy, Clone)] + pub struct RtcpNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RtcpNotificationRef<'a> { + pub fn data(&self) -> ::planus::Result<::planus::Vector<'a, u8>> { + self.0.access_required(0, "RtcpNotification", "data") + } + } + + impl<'a> ::core::fmt::Debug for RtcpNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RtcpNotificationRef"); + f.field("data", &self.data()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RtcpNotification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RtcpNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + data: value.data()?.to_vec()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RtcpNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RtcpNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RtcpNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RtcpNotification { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RtcpNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[RtcpNotificationRef]", "read_as_root", 0) + }) + } + } + } + pub mod transport { + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum Protocol { + Udp = 1, + Tcp = 2, + } + + impl ::core::convert::TryFrom for Protocol { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 1 => ::core::result::Result::Ok(Protocol::Udp), + 2 => ::core::result::Result::Ok(Protocol::Tcp), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: Protocol) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for Protocol { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for Protocol { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for Protocol { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> Protocol { + *self + } + } + + impl ::planus::WriteAsDefault for Protocol { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &Protocol, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for Protocol { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for Protocol { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for Protocol { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "Protocol", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for Protocol { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ListenIp { + pub ip: ::planus::alloc::string::String, + pub announced_ip: ::core::option::Option<::planus::alloc::string::String>, + } + + impl ListenIp { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ip: impl ::planus::WriteAs<::planus::Offset>, + field_announced_ip: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + ) -> ::planus::Offset { + let prepared_ip = field_ip.prepare(builder); + + let prepared_announced_ip = field_announced_ip.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_announced_ip.is_some() { + table_writer.calculate_size::<::planus::Offset>(4); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_ip); + if let ::core::option::Option::Some(prepared_announced_ip) = + prepared_announced_ip + { + table_writer.write::<_, _, 4>(1, &prepared_announced_ip); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ListenIp { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ListenIp { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ListenIp { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ListenIp::create(builder, &self.ip, &self.announced_ip) + } + } + + #[derive(Copy, Clone)] + pub struct ListenIpRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ListenIpRef<'a> { + pub fn ip(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "ListenIp", "ip") + } + + pub fn announced_ip( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(1, "ListenIp", "announced_ip") + } + } + + impl<'a> ::core::fmt::Debug for ListenIpRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ListenIpRef"); + f.field("ip", &self.ip()); + if let ::core::option::Option::Some(field_announced_ip) = + self.announced_ip().transpose() + { + f.field("announced_ip", &field_announced_ip); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ListenIp { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ListenIpRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ip: ::core::convert::TryInto::try_into(value.ip()?)?, + announced_ip: if let ::core::option::Option::Some(announced_ip) = + value.announced_ip()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + announced_ip, + )?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ListenIpRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ListenIpRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ListenIpRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ListenIp { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ListenIpRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ListenIpRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct RestartIceResponse { + pub username_fragment: ::planus::alloc::string::String, + pub password: ::planus::alloc::string::String, + pub ice_lite: bool, + } + + impl RestartIceResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_username_fragment: impl ::planus::WriteAs<::planus::Offset>, + field_password: impl ::planus::WriteAs<::planus::Offset>, + field_ice_lite: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_username_fragment = field_username_fragment.prepare(builder); + + let prepared_password = field_password.prepare(builder); + + let prepared_ice_lite = field_ice_lite.prepare(builder, &false); + + let mut table_writer = + ::planus::table_writer::TableWriter::<8, 9>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + if prepared_ice_lite.is_some() { + table_writer.calculate_size::(6); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_username_fragment); + table_writer.write::<_, _, 4>(1, &prepared_password); + if let ::core::option::Option::Some(prepared_ice_lite) = prepared_ice_lite { + table_writer.write::<_, _, 1>(2, &prepared_ice_lite); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RestartIceResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RestartIceResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RestartIceResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + RestartIceResponse::create( + builder, + &self.username_fragment, + &self.password, + &self.ice_lite, + ) + } + } + + #[derive(Copy, Clone)] + pub struct RestartIceResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RestartIceResponseRef<'a> { + pub fn username_fragment(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "RestartIceResponse", "username_fragment") + } + + pub fn password(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "RestartIceResponse", "password") + } + + pub fn ice_lite(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "RestartIceResponse", "ice_lite")? + .unwrap_or(false), + ) + } + } + + impl<'a> ::core::fmt::Debug for RestartIceResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RestartIceResponseRef"); + f.field("username_fragment", &self.username_fragment()); + f.field("password", &self.password()); + f.field("ice_lite", &self.ice_lite()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RestartIceResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RestartIceResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + username_fragment: ::core::convert::TryInto::try_into( + value.username_fragment()?, + )?, + password: ::core::convert::TryInto::try_into(value.password()?)?, + ice_lite: ::core::convert::TryInto::try_into(value.ice_lite()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RestartIceResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RestartIceResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RestartIceResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RestartIceResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RestartIceResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[RestartIceResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct ConsumeRequest { + pub consumer_id: ::planus::alloc::string::String, + pub producer_id: ::planus::alloc::string::String, + pub kind: super::rtp_parameters::MediaKind, + pub rtp_parameters: + ::planus::alloc::boxed::Box, + pub type_: super::rtp_parameters::Type, + pub consumable_rtp_encodings: + ::planus::alloc::vec::Vec, + pub paused: bool, + pub preferred_layers: ::core::option::Option< + ::planus::alloc::boxed::Box, + >, + pub ignore_dtx: bool, + } + + impl ConsumeRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_consumer_id: impl ::planus::WriteAs<::planus::Offset>, + field_producer_id: impl ::planus::WriteAs<::planus::Offset>, + field_kind: impl ::planus::WriteAsDefault< + super::rtp_parameters::MediaKind, + super::rtp_parameters::MediaKind, + >, + field_rtp_parameters: impl ::planus::WriteAs< + ::planus::Offset, + >, + field_type_: impl ::planus::WriteAsDefault< + super::rtp_parameters::Type, + super::rtp_parameters::Type, + >, + field_consumable_rtp_encodings: impl ::planus::WriteAs< + ::planus::Offset< + [::planus::Offset], + >, + >, + field_paused: impl ::planus::WriteAsDefault, + field_preferred_layers: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + field_ignore_dtx: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_consumer_id = field_consumer_id.prepare(builder); + + let prepared_producer_id = field_producer_id.prepare(builder); + + let prepared_kind = + field_kind.prepare(builder, &super::rtp_parameters::MediaKind::All); + + let prepared_rtp_parameters = field_rtp_parameters.prepare(builder); + + let prepared_type_ = + field_type_.prepare(builder, &super::rtp_parameters::Type::None); + + let prepared_consumable_rtp_encodings = + field_consumable_rtp_encodings.prepare(builder); + + let prepared_paused = field_paused.prepare(builder, &false); + + let prepared_preferred_layers = field_preferred_layers.prepare(builder); + + let prepared_ignore_dtx = field_ignore_dtx.prepare(builder, &false); + + let mut table_writer = + ::planus::table_writer::TableWriter::<20, 24>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + if prepared_kind.is_some() { + table_writer.calculate_size::(6); + } + table_writer + .calculate_size::<::planus::Offset>( + 8, + ); + if prepared_type_.is_some() { + table_writer.calculate_size::(10); + } + table_writer.calculate_size::<::planus::Offset< + [::planus::Offset], + >>(12); + if prepared_paused.is_some() { + table_writer.calculate_size::(14); + } + if prepared_preferred_layers.is_some() { + table_writer + .calculate_size::<::planus::Offset>( + 16, + ); + } + if prepared_ignore_dtx.is_some() { + table_writer.calculate_size::(18); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_consumer_id); + table_writer.write::<_, _, 4>(1, &prepared_producer_id); + table_writer.write::<_, _, 4>(3, &prepared_rtp_parameters); + table_writer.write::<_, _, 4>(5, &prepared_consumable_rtp_encodings); + if let ::core::option::Option::Some(prepared_preferred_layers) = + prepared_preferred_layers + { + table_writer.write::<_, _, 4>(7, &prepared_preferred_layers); + } + if let ::core::option::Option::Some(prepared_kind) = prepared_kind { + table_writer.write::<_, _, 1>(2, &prepared_kind); + } + if let ::core::option::Option::Some(prepared_type_) = prepared_type_ { + table_writer.write::<_, _, 1>(4, &prepared_type_); + } + if let ::core::option::Option::Some(prepared_paused) = prepared_paused { + table_writer.write::<_, _, 1>(6, &prepared_paused); + } + if let ::core::option::Option::Some(prepared_ignore_dtx) = + prepared_ignore_dtx + { + table_writer.write::<_, _, 1>(8, &prepared_ignore_dtx); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ConsumeRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ConsumeRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ConsumeRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ConsumeRequest::create( + builder, + &self.consumer_id, + &self.producer_id, + &self.kind, + &self.rtp_parameters, + &self.type_, + &self.consumable_rtp_encodings, + &self.paused, + &self.preferred_layers, + &self.ignore_dtx, + ) + } + } + + #[derive(Copy, Clone)] + pub struct ConsumeRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ConsumeRequestRef<'a> { + pub fn consumer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "ConsumeRequest", "consumer_id") + } + + pub fn producer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "ConsumeRequest", "producer_id") + } + + pub fn kind(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "ConsumeRequest", "kind")? + .unwrap_or(super::rtp_parameters::MediaKind::All), + ) + } + + pub fn rtp_parameters( + &self, + ) -> ::planus::Result> { + self.0 + .access_required(3, "ConsumeRequest", "rtp_parameters") + } + + pub fn type_(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(4, "ConsumeRequest", "type_")? + .unwrap_or(super::rtp_parameters::Type::None), + ) + } + + pub fn consumable_rtp_encodings( + &self, + ) -> ::planus::Result< + ::planus::Vector< + 'a, + ::planus::Result>, + >, + > { + self.0 + .access_required(5, "ConsumeRequest", "consumable_rtp_encodings") + } + + pub fn paused(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(6, "ConsumeRequest", "paused")? + .unwrap_or(false), + ) + } + + pub fn preferred_layers( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(7, "ConsumeRequest", "preferred_layers") + } + + pub fn ignore_dtx(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(8, "ConsumeRequest", "ignore_dtx")? + .unwrap_or(false), + ) + } + } + + impl<'a> ::core::fmt::Debug for ConsumeRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ConsumeRequestRef"); + f.field("consumer_id", &self.consumer_id()); + f.field("producer_id", &self.producer_id()); + f.field("kind", &self.kind()); + f.field("rtp_parameters", &self.rtp_parameters()); + f.field("type_", &self.type_()); + f.field("consumable_rtp_encodings", &self.consumable_rtp_encodings()); + f.field("paused", &self.paused()); + if let ::core::option::Option::Some(field_preferred_layers) = + self.preferred_layers().transpose() + { + f.field("preferred_layers", &field_preferred_layers); + } + f.field("ignore_dtx", &self.ignore_dtx()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ConsumeRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ConsumeRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + consumer_id: ::core::convert::TryInto::try_into(value.consumer_id()?)?, + producer_id: ::core::convert::TryInto::try_into(value.producer_id()?)?, + kind: ::core::convert::TryInto::try_into(value.kind()?)?, + rtp_parameters: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.rtp_parameters()?)?, + ), + type_: ::core::convert::TryInto::try_into(value.type_()?)?, + consumable_rtp_encodings: value + .consumable_rtp_encodings()? + .to_vec_result()?, + paused: ::core::convert::TryInto::try_into(value.paused()?)?, + preferred_layers: if let ::core::option::Option::Some(preferred_layers) = + value.preferred_layers()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(preferred_layers)?, + )) + } else { + ::core::option::Option::None + }, + ignore_dtx: ::core::convert::TryInto::try_into(value.ignore_dtx()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ConsumeRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ConsumeRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ConsumeRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ConsumeRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ConsumeRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ConsumeRequestRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ConsumeResponse { + pub paused: bool, + pub producer_paused: bool, + pub score: ::core::option::Option< + ::planus::alloc::boxed::Box, + >, + pub preferred_layers: ::core::option::Option< + ::planus::alloc::boxed::Box, + >, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for ConsumeResponse { + fn default() -> Self { + Self { + paused: false, + producer_paused: false, + score: ::core::default::Default::default(), + preferred_layers: ::core::default::Default::default(), + } + } + } + + impl ConsumeResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_paused: impl ::planus::WriteAsDefault, + field_producer_paused: impl ::planus::WriteAsDefault, + field_score: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + field_preferred_layers: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_paused = field_paused.prepare(builder, &false); + + let prepared_producer_paused = field_producer_paused.prepare(builder, &false); + + let prepared_score = field_score.prepare(builder); + + let prepared_preferred_layers = field_preferred_layers.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<10, 10>::new(builder); + + if prepared_paused.is_some() { + table_writer.calculate_size::(2); + } + if prepared_producer_paused.is_some() { + table_writer.calculate_size::(4); + } + if prepared_score.is_some() { + table_writer + .calculate_size::<::planus::Offset>(6); + } + if prepared_preferred_layers.is_some() { + table_writer + .calculate_size::<::planus::Offset>(8); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_score) = prepared_score { + table_writer.write::<_, _, 4>(2, &prepared_score); + } + if let ::core::option::Option::Some(prepared_preferred_layers) = + prepared_preferred_layers + { + table_writer.write::<_, _, 4>(3, &prepared_preferred_layers); + } + if let ::core::option::Option::Some(prepared_paused) = prepared_paused { + table_writer.write::<_, _, 1>(0, &prepared_paused); + } + if let ::core::option::Option::Some(prepared_producer_paused) = + prepared_producer_paused + { + table_writer.write::<_, _, 1>(1, &prepared_producer_paused); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ConsumeResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ConsumeResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ConsumeResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ConsumeResponse::create( + builder, + &self.paused, + &self.producer_paused, + &self.score, + &self.preferred_layers, + ) + } + } + + #[derive(Copy, Clone)] + pub struct ConsumeResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ConsumeResponseRef<'a> { + pub fn paused(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "ConsumeResponse", "paused")? + .unwrap_or(false), + ) + } + + pub fn producer_paused(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "ConsumeResponse", "producer_paused")? + .unwrap_or(false), + ) + } + + pub fn score( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(2, "ConsumeResponse", "score") + } + + pub fn preferred_layers( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(3, "ConsumeResponse", "preferred_layers") + } + } + + impl<'a> ::core::fmt::Debug for ConsumeResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ConsumeResponseRef"); + f.field("paused", &self.paused()); + f.field("producer_paused", &self.producer_paused()); + if let ::core::option::Option::Some(field_score) = self.score().transpose() { + f.field("score", &field_score); + } + if let ::core::option::Option::Some(field_preferred_layers) = + self.preferred_layers().transpose() + { + f.field("preferred_layers", &field_preferred_layers); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ConsumeResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ConsumeResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + paused: ::core::convert::TryInto::try_into(value.paused()?)?, + producer_paused: ::core::convert::TryInto::try_into( + value.producer_paused()?, + )?, + score: if let ::core::option::Option::Some(score) = value.score()? { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(score)?, + )) + } else { + ::core::option::Option::None + }, + preferred_layers: if let ::core::option::Option::Some(preferred_layers) = + value.preferred_layers()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(preferred_layers)?, + )) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ConsumeResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ConsumeResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ConsumeResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ConsumeResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ConsumeResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ConsumeResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct ProduceRequest { + pub producer_id: ::planus::alloc::string::String, + pub kind: super::rtp_parameters::MediaKind, + pub rtp_parameters: + ::planus::alloc::boxed::Box, + pub rtp_mapping: ::planus::alloc::boxed::Box, + pub key_frame_request_delay: u16, + pub paused: bool, + } + + impl ProduceRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_producer_id: impl ::planus::WriteAs<::planus::Offset>, + field_kind: impl ::planus::WriteAsDefault< + super::rtp_parameters::MediaKind, + super::rtp_parameters::MediaKind, + >, + field_rtp_parameters: impl ::planus::WriteAs< + ::planus::Offset, + >, + field_rtp_mapping: impl ::planus::WriteAs< + ::planus::Offset, + >, + field_key_frame_request_delay: impl ::planus::WriteAsDefault, + field_paused: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_producer_id = field_producer_id.prepare(builder); + + let prepared_kind = + field_kind.prepare(builder, &super::rtp_parameters::MediaKind::All); + + let prepared_rtp_parameters = field_rtp_parameters.prepare(builder); + + let prepared_rtp_mapping = field_rtp_mapping.prepare(builder); + + let prepared_key_frame_request_delay = + field_key_frame_request_delay.prepare(builder, &0); + + let prepared_paused = field_paused.prepare(builder, &false); + + let mut table_writer = + ::planus::table_writer::TableWriter::<14, 16>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_kind.is_some() { + table_writer.calculate_size::(4); + } + table_writer + .calculate_size::<::planus::Offset>( + 6, + ); + table_writer + .calculate_size::<::planus::Offset>(8); + if prepared_key_frame_request_delay.is_some() { + table_writer.calculate_size::(10); + } + if prepared_paused.is_some() { + table_writer.calculate_size::(12); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_producer_id); + table_writer.write::<_, _, 4>(2, &prepared_rtp_parameters); + table_writer.write::<_, _, 4>(3, &prepared_rtp_mapping); + if let ::core::option::Option::Some(prepared_key_frame_request_delay) = + prepared_key_frame_request_delay + { + table_writer.write::<_, _, 2>(4, &prepared_key_frame_request_delay); + } + if let ::core::option::Option::Some(prepared_kind) = prepared_kind { + table_writer.write::<_, _, 1>(1, &prepared_kind); + } + if let ::core::option::Option::Some(prepared_paused) = prepared_paused { + table_writer.write::<_, _, 1>(5, &prepared_paused); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ProduceRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ProduceRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ProduceRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ProduceRequest::create( + builder, + &self.producer_id, + &self.kind, + &self.rtp_parameters, + &self.rtp_mapping, + &self.key_frame_request_delay, + &self.paused, + ) + } + } + + #[derive(Copy, Clone)] + pub struct ProduceRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ProduceRequestRef<'a> { + pub fn producer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "ProduceRequest", "producer_id") + } + + pub fn kind(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "ProduceRequest", "kind")? + .unwrap_or(super::rtp_parameters::MediaKind::All), + ) + } + + pub fn rtp_parameters( + &self, + ) -> ::planus::Result> { + self.0 + .access_required(2, "ProduceRequest", "rtp_parameters") + } + + pub fn rtp_mapping( + &self, + ) -> ::planus::Result> { + self.0.access_required(3, "ProduceRequest", "rtp_mapping") + } + + pub fn key_frame_request_delay(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(4, "ProduceRequest", "key_frame_request_delay")? + .unwrap_or(0), + ) + } + + pub fn paused(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(5, "ProduceRequest", "paused")? + .unwrap_or(false), + ) + } + } + + impl<'a> ::core::fmt::Debug for ProduceRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ProduceRequestRef"); + f.field("producer_id", &self.producer_id()); + f.field("kind", &self.kind()); + f.field("rtp_parameters", &self.rtp_parameters()); + f.field("rtp_mapping", &self.rtp_mapping()); + f.field("key_frame_request_delay", &self.key_frame_request_delay()); + f.field("paused", &self.paused()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ProduceRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ProduceRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + producer_id: ::core::convert::TryInto::try_into(value.producer_id()?)?, + kind: ::core::convert::TryInto::try_into(value.kind()?)?, + rtp_parameters: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.rtp_parameters()?)?, + ), + rtp_mapping: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.rtp_mapping()?)?, + ), + key_frame_request_delay: ::core::convert::TryInto::try_into( + value.key_frame_request_delay()?, + )?, + paused: ::core::convert::TryInto::try_into(value.paused()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ProduceRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ProduceRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ProduceRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ProduceRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ProduceRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ProduceRequestRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ProduceResponse { + pub type_: super::rtp_parameters::Type, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for ProduceResponse { + fn default() -> Self { + Self { + type_: super::rtp_parameters::Type::None, + } + } + } + + impl ProduceResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_type_: impl ::planus::WriteAsDefault< + super::rtp_parameters::Type, + super::rtp_parameters::Type, + >, + ) -> ::planus::Offset { + let prepared_type_ = + field_type_.prepare(builder, &super::rtp_parameters::Type::None); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 1>::new(builder); + + if prepared_type_.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_type_) = prepared_type_ { + table_writer.write::<_, _, 1>(0, &prepared_type_); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ProduceResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ProduceResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ProduceResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ProduceResponse::create(builder, &self.type_) + } + } + + #[derive(Copy, Clone)] + pub struct ProduceResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ProduceResponseRef<'a> { + pub fn type_(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "ProduceResponse", "type_")? + .unwrap_or(super::rtp_parameters::Type::None), + ) + } + } + + impl<'a> ::core::fmt::Debug for ProduceResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ProduceResponseRef"); + f.field("type_", &self.type_()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ProduceResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ProduceResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + type_: ::core::convert::TryInto::try_into(value.type_()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ProduceResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ProduceResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ProduceResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ProduceResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ProduceResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ProduceResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ProduceDataRequest { + pub data_producer_id: ::planus::alloc::string::String, + pub type_: ::planus::alloc::string::String, + pub sctp_stream_parameters: ::core::option::Option< + ::planus::alloc::boxed::Box, + >, + pub label: ::core::option::Option<::planus::alloc::string::String>, + pub protocol: ::core::option::Option<::planus::alloc::string::String>, + } + + impl ProduceDataRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_data_producer_id: impl ::planus::WriteAs<::planus::Offset>, + field_type_: impl ::planus::WriteAs<::planus::Offset>, + field_sctp_stream_parameters: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + field_label: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + field_protocol: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + ) -> ::planus::Offset { + let prepared_data_producer_id = field_data_producer_id.prepare(builder); + + let prepared_type_ = field_type_.prepare(builder); + + let prepared_sctp_stream_parameters = + field_sctp_stream_parameters.prepare(builder); + + let prepared_label = field_label.prepare(builder); + + let prepared_protocol = field_protocol.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<12, 20>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + if prepared_sctp_stream_parameters.is_some() { + table_writer.calculate_size::<::planus::Offset>(6); + } + if prepared_label.is_some() { + table_writer.calculate_size::<::planus::Offset>(8); + } + if prepared_protocol.is_some() { + table_writer.calculate_size::<::planus::Offset>(10); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_data_producer_id); + table_writer.write::<_, _, 4>(1, &prepared_type_); + if let ::core::option::Option::Some(prepared_sctp_stream_parameters) = + prepared_sctp_stream_parameters + { + table_writer.write::<_, _, 4>(2, &prepared_sctp_stream_parameters); + } + if let ::core::option::Option::Some(prepared_label) = prepared_label { + table_writer.write::<_, _, 4>(3, &prepared_label); + } + if let ::core::option::Option::Some(prepared_protocol) = prepared_protocol { + table_writer.write::<_, _, 4>(4, &prepared_protocol); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ProduceDataRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ProduceDataRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ProduceDataRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ProduceDataRequest::create( + builder, + &self.data_producer_id, + &self.type_, + &self.sctp_stream_parameters, + &self.label, + &self.protocol, + ) + } + } + + #[derive(Copy, Clone)] + pub struct ProduceDataRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ProduceDataRequestRef<'a> { + pub fn data_producer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "ProduceDataRequest", "data_producer_id") + } + + pub fn type_(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "ProduceDataRequest", "type_") + } + + pub fn sctp_stream_parameters( + &self, + ) -> ::planus::Result< + ::core::option::Option>, + > { + self.0 + .access(2, "ProduceDataRequest", "sctp_stream_parameters") + } + + pub fn label( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(3, "ProduceDataRequest", "label") + } + + pub fn protocol( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(4, "ProduceDataRequest", "protocol") + } + } + + impl<'a> ::core::fmt::Debug for ProduceDataRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ProduceDataRequestRef"); + f.field("data_producer_id", &self.data_producer_id()); + f.field("type_", &self.type_()); + if let ::core::option::Option::Some(field_sctp_stream_parameters) = + self.sctp_stream_parameters().transpose() + { + f.field("sctp_stream_parameters", &field_sctp_stream_parameters); + } + if let ::core::option::Option::Some(field_label) = self.label().transpose() { + f.field("label", &field_label); + } + if let ::core::option::Option::Some(field_protocol) = + self.protocol().transpose() + { + f.field("protocol", &field_protocol); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ProduceDataRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ProduceDataRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + data_producer_id: ::core::convert::TryInto::try_into( + value.data_producer_id()?, + )?, + type_: ::core::convert::TryInto::try_into(value.type_()?)?, + sctp_stream_parameters: if let ::core::option::Option::Some( + sctp_stream_parameters, + ) = value.sctp_stream_parameters()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(sctp_stream_parameters)?, + )) + } else { + ::core::option::Option::None + }, + label: if let ::core::option::Option::Some(label) = value.label()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(label)?) + } else { + ::core::option::Option::None + }, + protocol: if let ::core::option::Option::Some(protocol) = + value.protocol()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + protocol, + )?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ProduceDataRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ProduceDataRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ProduceDataRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ProduceDataRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ProduceDataRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ProduceDataRequestRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ConsumeDataRequest { + pub data_consumer_id: ::planus::alloc::string::String, + pub data_producer_id: ::planus::alloc::string::String, + pub type_: ::planus::alloc::string::String, + pub sctp_stream_parameters: ::core::option::Option< + ::planus::alloc::boxed::Box, + >, + pub label: ::core::option::Option<::planus::alloc::string::String>, + pub protocol: ::core::option::Option<::planus::alloc::string::String>, + } + + impl ConsumeDataRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_data_consumer_id: impl ::planus::WriteAs<::planus::Offset>, + field_data_producer_id: impl ::planus::WriteAs<::planus::Offset>, + field_type_: impl ::planus::WriteAs<::planus::Offset>, + field_sctp_stream_parameters: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + field_label: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + field_protocol: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + ) -> ::planus::Offset { + let prepared_data_consumer_id = field_data_consumer_id.prepare(builder); + + let prepared_data_producer_id = field_data_producer_id.prepare(builder); + + let prepared_type_ = field_type_.prepare(builder); + + let prepared_sctp_stream_parameters = + field_sctp_stream_parameters.prepare(builder); + + let prepared_label = field_label.prepare(builder); + + let prepared_protocol = field_protocol.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<14, 24>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + table_writer.calculate_size::<::planus::Offset>(6); + if prepared_sctp_stream_parameters.is_some() { + table_writer.calculate_size::<::planus::Offset>(8); + } + if prepared_label.is_some() { + table_writer.calculate_size::<::planus::Offset>(10); + } + if prepared_protocol.is_some() { + table_writer.calculate_size::<::planus::Offset>(12); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_data_consumer_id); + table_writer.write::<_, _, 4>(1, &prepared_data_producer_id); + table_writer.write::<_, _, 4>(2, &prepared_type_); + if let ::core::option::Option::Some(prepared_sctp_stream_parameters) = + prepared_sctp_stream_parameters + { + table_writer.write::<_, _, 4>(3, &prepared_sctp_stream_parameters); + } + if let ::core::option::Option::Some(prepared_label) = prepared_label { + table_writer.write::<_, _, 4>(4, &prepared_label); + } + if let ::core::option::Option::Some(prepared_protocol) = prepared_protocol { + table_writer.write::<_, _, 4>(5, &prepared_protocol); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ConsumeDataRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ConsumeDataRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ConsumeDataRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ConsumeDataRequest::create( + builder, + &self.data_consumer_id, + &self.data_producer_id, + &self.type_, + &self.sctp_stream_parameters, + &self.label, + &self.protocol, + ) + } + } + + #[derive(Copy, Clone)] + pub struct ConsumeDataRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ConsumeDataRequestRef<'a> { + pub fn data_consumer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "ConsumeDataRequest", "data_consumer_id") + } + + pub fn data_producer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(1, "ConsumeDataRequest", "data_producer_id") + } + + pub fn type_(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(2, "ConsumeDataRequest", "type_") + } + + pub fn sctp_stream_parameters( + &self, + ) -> ::planus::Result< + ::core::option::Option>, + > { + self.0 + .access(3, "ConsumeDataRequest", "sctp_stream_parameters") + } + + pub fn label( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(4, "ConsumeDataRequest", "label") + } + + pub fn protocol( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(5, "ConsumeDataRequest", "protocol") + } + } + + impl<'a> ::core::fmt::Debug for ConsumeDataRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ConsumeDataRequestRef"); + f.field("data_consumer_id", &self.data_consumer_id()); + f.field("data_producer_id", &self.data_producer_id()); + f.field("type_", &self.type_()); + if let ::core::option::Option::Some(field_sctp_stream_parameters) = + self.sctp_stream_parameters().transpose() + { + f.field("sctp_stream_parameters", &field_sctp_stream_parameters); + } + if let ::core::option::Option::Some(field_label) = self.label().transpose() { + f.field("label", &field_label); + } + if let ::core::option::Option::Some(field_protocol) = + self.protocol().transpose() + { + f.field("protocol", &field_protocol); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ConsumeDataRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ConsumeDataRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + data_consumer_id: ::core::convert::TryInto::try_into( + value.data_consumer_id()?, + )?, + data_producer_id: ::core::convert::TryInto::try_into( + value.data_producer_id()?, + )?, + type_: ::core::convert::TryInto::try_into(value.type_()?)?, + sctp_stream_parameters: if let ::core::option::Option::Some( + sctp_stream_parameters, + ) = value.sctp_stream_parameters()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(sctp_stream_parameters)?, + )) + } else { + ::core::option::Option::None + }, + label: if let ::core::option::Option::Some(label) = value.label()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(label)?) + } else { + ::core::option::Option::None + }, + protocol: if let ::core::option::Option::Some(protocol) = + value.protocol()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + protocol, + )?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ConsumeDataRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ConsumeDataRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ConsumeDataRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ConsumeDataRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ConsumeDataRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ConsumeDataRequestRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Tuple { + pub local_ip: ::planus::alloc::string::String, + pub local_port: u16, + pub remote_ip: ::planus::alloc::string::String, + pub remote_port: u16, + pub protocol: ::planus::alloc::string::String, + } + + impl Tuple { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_local_ip: impl ::planus::WriteAs<::planus::Offset>, + field_local_port: impl ::planus::WriteAsDefault, + field_remote_ip: impl ::planus::WriteAs<::planus::Offset>, + field_remote_port: impl ::planus::WriteAsDefault, + field_protocol: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_local_ip = field_local_ip.prepare(builder); + + let prepared_local_port = field_local_port.prepare(builder, &0); + + let prepared_remote_ip = field_remote_ip.prepare(builder); + + let prepared_remote_port = field_remote_port.prepare(builder, &0); + + let prepared_protocol = field_protocol.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<12, 16>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_local_port.is_some() { + table_writer.calculate_size::(4); + } + table_writer.calculate_size::<::planus::Offset>(6); + if prepared_remote_port.is_some() { + table_writer.calculate_size::(8); + } + table_writer.calculate_size::<::planus::Offset>(10); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_local_ip); + table_writer.write::<_, _, 4>(2, &prepared_remote_ip); + table_writer.write::<_, _, 4>(4, &prepared_protocol); + if let ::core::option::Option::Some(prepared_local_port) = + prepared_local_port + { + table_writer.write::<_, _, 2>(1, &prepared_local_port); + } + if let ::core::option::Option::Some(prepared_remote_port) = + prepared_remote_port + { + table_writer.write::<_, _, 2>(3, &prepared_remote_port); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Tuple { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Tuple { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Tuple { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Tuple::create( + builder, + &self.local_ip, + &self.local_port, + &self.remote_ip, + &self.remote_port, + &self.protocol, + ) + } + } + + #[derive(Copy, Clone)] + pub struct TupleRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> TupleRef<'a> { + pub fn local_ip(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "Tuple", "local_ip") + } + + pub fn local_port(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(1, "Tuple", "local_port")?.unwrap_or(0), + ) + } + + pub fn remote_ip(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(2, "Tuple", "remote_ip") + } + + pub fn remote_port(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(3, "Tuple", "remote_port")?.unwrap_or(0), + ) + } + + pub fn protocol(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(4, "Tuple", "protocol") + } + } + + impl<'a> ::core::fmt::Debug for TupleRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("TupleRef"); + f.field("local_ip", &self.local_ip()); + f.field("local_port", &self.local_port()); + f.field("remote_ip", &self.remote_ip()); + f.field("remote_port", &self.remote_port()); + f.field("protocol", &self.protocol()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Tuple { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: TupleRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + local_ip: ::core::convert::TryInto::try_into(value.local_ip()?)?, + local_port: ::core::convert::TryInto::try_into(value.local_port()?)?, + remote_ip: ::core::convert::TryInto::try_into(value.remote_ip()?)?, + remote_port: ::core::convert::TryInto::try_into(value.remote_port()?)?, + protocol: ::core::convert::TryInto::try_into(value.protocol()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for TupleRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for TupleRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[TupleRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Tuple { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for TupleRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[TupleRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SrtpParameters { + pub crypto_suite: ::planus::alloc::string::String, + pub key_base64: ::planus::alloc::string::String, + } + + impl SrtpParameters { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_crypto_suite: impl ::planus::WriteAs<::planus::Offset>, + field_key_base64: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_crypto_suite = field_crypto_suite.prepare(builder); + + let prepared_key_base64 = field_key_base64.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_crypto_suite); + table_writer.write::<_, _, 4>(1, &prepared_key_base64); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for SrtpParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for SrtpParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SrtpParameters { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SrtpParameters::create(builder, &self.crypto_suite, &self.key_base64) + } + } + + #[derive(Copy, Clone)] + pub struct SrtpParametersRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SrtpParametersRef<'a> { + pub fn crypto_suite(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "SrtpParameters", "crypto_suite") + } + + pub fn key_base64(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "SrtpParameters", "key_base64") + } + } + + impl<'a> ::core::fmt::Debug for SrtpParametersRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SrtpParametersRef"); + f.field("crypto_suite", &self.crypto_suite()); + f.field("key_base64", &self.key_base64()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for SrtpParameters { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SrtpParametersRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + crypto_suite: ::core::convert::TryInto::try_into(value.crypto_suite()?)?, + key_base64: ::core::convert::TryInto::try_into(value.key_base64()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SrtpParametersRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SrtpParametersRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SrtpParametersRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for SrtpParameters { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SrtpParametersRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[SrtpParametersRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct RtpListener { + pub ssrc_table: ::planus::alloc::vec::Vec, + pub mid_table: ::planus::alloc::vec::Vec, + pub rid_table: ::planus::alloc::vec::Vec, + } + + impl RtpListener { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ssrc_table: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_mid_table: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_rid_table: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_ssrc_table = field_ssrc_table.prepare(builder); + + let prepared_mid_table = field_mid_table.prepare(builder); + + let prepared_rid_table = field_rid_table.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<8, 12>::new(builder); + + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(2); + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(4); + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(6); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_ssrc_table); + table_writer.write::<_, _, 4>(1, &prepared_mid_table); + table_writer.write::<_, _, 4>(2, &prepared_rid_table); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RtpListener { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RtpListener { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RtpListener { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + RtpListener::create(builder, &self.ssrc_table, &self.mid_table, &self.rid_table) + } + } + + #[derive(Copy, Clone)] + pub struct RtpListenerRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RtpListenerRef<'a> { + pub fn ssrc_table( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result>>, + > { + self.0.access_required(0, "RtpListener", "ssrc_table") + } + + pub fn mid_table( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result>>, + > { + self.0.access_required(1, "RtpListener", "mid_table") + } + + pub fn rid_table( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result>>, + > { + self.0.access_required(2, "RtpListener", "rid_table") + } + } + + impl<'a> ::core::fmt::Debug for RtpListenerRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RtpListenerRef"); + f.field("ssrc_table", &self.ssrc_table()); + f.field("mid_table", &self.mid_table()); + f.field("rid_table", &self.rid_table()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RtpListener { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RtpListenerRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ssrc_table: value.ssrc_table()?.to_vec_result()?, + mid_table: value.mid_table()?.to_vec_result()?, + rid_table: value.rid_table()?.to_vec_result()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RtpListenerRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RtpListenerRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RtpListenerRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RtpListener { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RtpListenerRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[RtpListenerRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SctpListener { + pub stream_id_table: ::planus::alloc::vec::Vec, + } + + impl SctpListener { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_stream_id_table: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_stream_id_table = field_stream_id_table.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_stream_id_table); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for SctpListener { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for SctpListener { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SctpListener { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SctpListener::create(builder, &self.stream_id_table) + } + } + + #[derive(Copy, Clone)] + pub struct SctpListenerRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SctpListenerRef<'a> { + pub fn stream_id_table( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result>>, + > { + self.0.access_required(0, "SctpListener", "stream_id_table") + } + } + + impl<'a> ::core::fmt::Debug for SctpListenerRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SctpListenerRef"); + f.field("stream_id_table", &self.stream_id_table()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for SctpListener { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SctpListenerRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + stream_id_table: value.stream_id_table()?.to_vec_result()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SctpListenerRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SctpListenerRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SctpListenerRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for SctpListener { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SctpListenerRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[SctpListenerRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Dump { + pub id: ::planus::alloc::string::String, + pub direct: bool, + pub producer_ids: ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + pub consumer_ids: ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + pub map_ssrc_consumer_id: ::planus::alloc::vec::Vec, + pub map_rtx_ssrc_consumer_id: + ::planus::alloc::vec::Vec, + pub data_producer_ids: ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + pub data_consumer_ids: ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + pub recv_rtp_header_extensions: + ::planus::alloc::vec::Vec, + pub rtp_listener: ::planus::alloc::boxed::Box, + pub max_message_size: u32, + pub sctp_parameters: ::core::option::Option< + ::planus::alloc::boxed::Box, + >, + pub sctp_state: ::core::option::Option<::planus::alloc::string::String>, + pub sctp_listener: + ::core::option::Option<::planus::alloc::boxed::Box>, + pub trace_event_types: ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + } + + impl Dump { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_id: impl ::planus::WriteAs<::planus::Offset>, + field_direct: impl ::planus::WriteAsDefault, + field_producer_ids: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_consumer_ids: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_map_ssrc_consumer_id: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_map_rtx_ssrc_consumer_id: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_data_producer_ids: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_data_consumer_ids: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_recv_rtp_header_extensions: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_rtp_listener: impl ::planus::WriteAs<::planus::Offset>, + field_max_message_size: impl ::planus::WriteAsDefault, + field_sctp_parameters: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + field_sctp_state: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + field_sctp_listener: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + field_trace_event_types: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_id = field_id.prepare(builder); + + let prepared_direct = field_direct.prepare(builder, &false); + + let prepared_producer_ids = field_producer_ids.prepare(builder); + + let prepared_consumer_ids = field_consumer_ids.prepare(builder); + + let prepared_map_ssrc_consumer_id = field_map_ssrc_consumer_id.prepare(builder); + + let prepared_map_rtx_ssrc_consumer_id = + field_map_rtx_ssrc_consumer_id.prepare(builder); + + let prepared_data_producer_ids = field_data_producer_ids.prepare(builder); + + let prepared_data_consumer_ids = field_data_consumer_ids.prepare(builder); + + let prepared_recv_rtp_header_extensions = + field_recv_rtp_header_extensions.prepare(builder); + + let prepared_rtp_listener = field_rtp_listener.prepare(builder); + + let prepared_max_message_size = field_max_message_size.prepare(builder, &0); + + let prepared_sctp_parameters = field_sctp_parameters.prepare(builder); + + let prepared_sctp_state = field_sctp_state.prepare(builder); + + let prepared_sctp_listener = field_sctp_listener.prepare(builder); + + let prepared_trace_event_types = field_trace_event_types.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<32, 57>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_direct.is_some() { + table_writer.calculate_size::(4); + } + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(6); + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(8); + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(10); + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(12); + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(14); + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(16); + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(18); + table_writer.calculate_size::<::planus::Offset>(20); + if prepared_max_message_size.is_some() { + table_writer.calculate_size::(22); + } + if prepared_sctp_parameters.is_some() { + table_writer.calculate_size::<::planus::Offset>(24); + } + if prepared_sctp_state.is_some() { + table_writer.calculate_size::<::planus::Offset>(26); + } + if prepared_sctp_listener.is_some() { + table_writer.calculate_size::<::planus::Offset>(28); + } + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(30); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_id); + table_writer.write::<_, _, 4>(2, &prepared_producer_ids); + table_writer.write::<_, _, 4>(3, &prepared_consumer_ids); + table_writer.write::<_, _, 4>(4, &prepared_map_ssrc_consumer_id); + table_writer.write::<_, _, 4>(5, &prepared_map_rtx_ssrc_consumer_id); + table_writer.write::<_, _, 4>(6, &prepared_data_producer_ids); + table_writer.write::<_, _, 4>(7, &prepared_data_consumer_ids); + table_writer.write::<_, _, 4>(8, &prepared_recv_rtp_header_extensions); + table_writer.write::<_, _, 4>(9, &prepared_rtp_listener); + if let ::core::option::Option::Some(prepared_max_message_size) = + prepared_max_message_size + { + table_writer.write::<_, _, 4>(10, &prepared_max_message_size); + } + if let ::core::option::Option::Some(prepared_sctp_parameters) = + prepared_sctp_parameters + { + table_writer.write::<_, _, 4>(11, &prepared_sctp_parameters); + } + if let ::core::option::Option::Some(prepared_sctp_state) = + prepared_sctp_state + { + table_writer.write::<_, _, 4>(12, &prepared_sctp_state); + } + if let ::core::option::Option::Some(prepared_sctp_listener) = + prepared_sctp_listener + { + table_writer.write::<_, _, 4>(13, &prepared_sctp_listener); + } + table_writer.write::<_, _, 4>(14, &prepared_trace_event_types); + if let ::core::option::Option::Some(prepared_direct) = prepared_direct { + table_writer.write::<_, _, 1>(1, &prepared_direct); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Dump { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Dump { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Dump { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Dump::create( + builder, + &self.id, + &self.direct, + &self.producer_ids, + &self.consumer_ids, + &self.map_ssrc_consumer_id, + &self.map_rtx_ssrc_consumer_id, + &self.data_producer_ids, + &self.data_consumer_ids, + &self.recv_rtp_header_extensions, + &self.rtp_listener, + &self.max_message_size, + &self.sctp_parameters, + &self.sctp_state, + &self.sctp_listener, + &self.trace_event_types, + ) + } + } + + #[derive(Copy, Clone)] + pub struct DumpRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DumpRef<'a> { + pub fn id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "Dump", "id") + } + + pub fn direct(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(1, "Dump", "direct")?.unwrap_or(false)) + } + + pub fn producer_ids( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + > { + self.0.access_required(2, "Dump", "producer_ids") + } + + pub fn consumer_ids( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + > { + self.0.access_required(3, "Dump", "consumer_ids") + } + + pub fn map_ssrc_consumer_id( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result>>, + > { + self.0.access_required(4, "Dump", "map_ssrc_consumer_id") + } + + pub fn map_rtx_ssrc_consumer_id( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result>>, + > { + self.0 + .access_required(5, "Dump", "map_rtx_ssrc_consumer_id") + } + + pub fn data_producer_ids( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + > { + self.0.access_required(6, "Dump", "data_producer_ids") + } + + pub fn data_consumer_ids( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + > { + self.0.access_required(7, "Dump", "data_consumer_ids") + } + + pub fn recv_rtp_header_extensions( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result>>, + > { + self.0 + .access_required(8, "Dump", "recv_rtp_header_extensions") + } + + pub fn rtp_listener(&self) -> ::planus::Result> { + self.0.access_required(9, "Dump", "rtp_listener") + } + + pub fn max_message_size(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(10, "Dump", "max_message_size")?.unwrap_or(0), + ) + } + + pub fn sctp_parameters( + &self, + ) -> ::planus::Result< + ::core::option::Option>, + > { + self.0.access(11, "Dump", "sctp_parameters") + } + + pub fn sctp_state( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(12, "Dump", "sctp_state") + } + + pub fn sctp_listener( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(13, "Dump", "sctp_listener") + } + + pub fn trace_event_types( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + > { + self.0.access_required(14, "Dump", "trace_event_types") + } + } + + impl<'a> ::core::fmt::Debug for DumpRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DumpRef"); + f.field("id", &self.id()); + f.field("direct", &self.direct()); + f.field("producer_ids", &self.producer_ids()); + f.field("consumer_ids", &self.consumer_ids()); + f.field("map_ssrc_consumer_id", &self.map_ssrc_consumer_id()); + f.field("map_rtx_ssrc_consumer_id", &self.map_rtx_ssrc_consumer_id()); + f.field("data_producer_ids", &self.data_producer_ids()); + f.field("data_consumer_ids", &self.data_consumer_ids()); + f.field( + "recv_rtp_header_extensions", + &self.recv_rtp_header_extensions(), + ); + f.field("rtp_listener", &self.rtp_listener()); + f.field("max_message_size", &self.max_message_size()); + if let ::core::option::Option::Some(field_sctp_parameters) = + self.sctp_parameters().transpose() + { + f.field("sctp_parameters", &field_sctp_parameters); + } + if let ::core::option::Option::Some(field_sctp_state) = + self.sctp_state().transpose() + { + f.field("sctp_state", &field_sctp_state); + } + if let ::core::option::Option::Some(field_sctp_listener) = + self.sctp_listener().transpose() + { + f.field("sctp_listener", &field_sctp_listener); + } + f.field("trace_event_types", &self.trace_event_types()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Dump { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DumpRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + id: ::core::convert::TryInto::try_into(value.id()?)?, + direct: ::core::convert::TryInto::try_into(value.direct()?)?, + producer_ids: value.producer_ids()?.to_vec_result()?, + consumer_ids: value.consumer_ids()?.to_vec_result()?, + map_ssrc_consumer_id: value.map_ssrc_consumer_id()?.to_vec_result()?, + map_rtx_ssrc_consumer_id: value + .map_rtx_ssrc_consumer_id()? + .to_vec_result()?, + data_producer_ids: value.data_producer_ids()?.to_vec_result()?, + data_consumer_ids: value.data_consumer_ids()?.to_vec_result()?, + recv_rtp_header_extensions: value + .recv_rtp_header_extensions()? + .to_vec_result()?, + rtp_listener: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.rtp_listener()?)?, + ), + max_message_size: ::core::convert::TryInto::try_into( + value.max_message_size()?, + )?, + sctp_parameters: if let ::core::option::Option::Some(sctp_parameters) = + value.sctp_parameters()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(sctp_parameters)?, + )) + } else { + ::core::option::Option::None + }, + sctp_state: if let ::core::option::Option::Some(sctp_state) = + value.sctp_state()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + sctp_state, + )?) + } else { + ::core::option::Option::None + }, + sctp_listener: if let ::core::option::Option::Some(sctp_listener) = + value.sctp_listener()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(sctp_listener)?, + )) + } else { + ::core::option::Option::None + }, + trace_event_types: value.trace_event_types()?.to_vec_result()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DumpRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DumpRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location("[DumpRef]", "get", buffer.offset_from_start) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Dump { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DumpRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[DumpRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Options { + pub direct: bool, + pub max_message_size: u32, + pub initial_available_outgoing_bitrate: u32, + pub enable_sctp: bool, + pub num_sctp_streams: ::core::option::Option< + ::planus::alloc::boxed::Box, + >, + pub max_sctp_message_size: u32, + pub sctp_send_buffer_size: u32, + pub is_data_channel: bool, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for Options { + fn default() -> Self { + Self { + direct: false, + max_message_size: 0, + initial_available_outgoing_bitrate: 0, + enable_sctp: false, + num_sctp_streams: ::core::default::Default::default(), + max_sctp_message_size: 0, + sctp_send_buffer_size: 0, + is_data_channel: false, + } + } + } + + impl Options { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_direct: impl ::planus::WriteAsDefault, + field_max_message_size: impl ::planus::WriteAsDefault, + field_initial_available_outgoing_bitrate: impl ::planus::WriteAsDefault, + field_enable_sctp: impl ::planus::WriteAsDefault, + field_num_sctp_streams: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + field_max_sctp_message_size: impl ::planus::WriteAsDefault, + field_sctp_send_buffer_size: impl ::planus::WriteAsDefault, + field_is_data_channel: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_direct = field_direct.prepare(builder, &false); + + let prepared_max_message_size = field_max_message_size.prepare(builder, &0); + + let prepared_initial_available_outgoing_bitrate = + field_initial_available_outgoing_bitrate.prepare(builder, &0); + + let prepared_enable_sctp = field_enable_sctp.prepare(builder, &false); + + let prepared_num_sctp_streams = field_num_sctp_streams.prepare(builder); + + let prepared_max_sctp_message_size = + field_max_sctp_message_size.prepare(builder, &0); + + let prepared_sctp_send_buffer_size = + field_sctp_send_buffer_size.prepare(builder, &0); + + let prepared_is_data_channel = field_is_data_channel.prepare(builder, &false); + + let mut table_writer = + ::planus::table_writer::TableWriter::<18, 23>::new(builder); + + if prepared_direct.is_some() { + table_writer.calculate_size::(2); + } + if prepared_max_message_size.is_some() { + table_writer.calculate_size::(4); + } + if prepared_initial_available_outgoing_bitrate.is_some() { + table_writer.calculate_size::(6); + } + if prepared_enable_sctp.is_some() { + table_writer.calculate_size::(8); + } + if prepared_num_sctp_streams.is_some() { + table_writer.calculate_size::<::planus::Offset>(10); + } + if prepared_max_sctp_message_size.is_some() { + table_writer.calculate_size::(12); + } + if prepared_sctp_send_buffer_size.is_some() { + table_writer.calculate_size::(14); + } + if prepared_is_data_channel.is_some() { + table_writer.calculate_size::(16); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_max_message_size) = + prepared_max_message_size + { + table_writer.write::<_, _, 4>(1, &prepared_max_message_size); + } + if let ::core::option::Option::Some( + prepared_initial_available_outgoing_bitrate, + ) = prepared_initial_available_outgoing_bitrate + { + table_writer + .write::<_, _, 4>(2, &prepared_initial_available_outgoing_bitrate); + } + if let ::core::option::Option::Some(prepared_num_sctp_streams) = + prepared_num_sctp_streams + { + table_writer.write::<_, _, 4>(4, &prepared_num_sctp_streams); + } + if let ::core::option::Option::Some(prepared_max_sctp_message_size) = + prepared_max_sctp_message_size + { + table_writer.write::<_, _, 4>(5, &prepared_max_sctp_message_size); + } + if let ::core::option::Option::Some(prepared_sctp_send_buffer_size) = + prepared_sctp_send_buffer_size + { + table_writer.write::<_, _, 4>(6, &prepared_sctp_send_buffer_size); + } + if let ::core::option::Option::Some(prepared_direct) = prepared_direct { + table_writer.write::<_, _, 1>(0, &prepared_direct); + } + if let ::core::option::Option::Some(prepared_enable_sctp) = + prepared_enable_sctp + { + table_writer.write::<_, _, 1>(3, &prepared_enable_sctp); + } + if let ::core::option::Option::Some(prepared_is_data_channel) = + prepared_is_data_channel + { + table_writer.write::<_, _, 1>(7, &prepared_is_data_channel); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Options { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Options { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Options { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Options::create( + builder, + &self.direct, + &self.max_message_size, + &self.initial_available_outgoing_bitrate, + &self.enable_sctp, + &self.num_sctp_streams, + &self.max_sctp_message_size, + &self.sctp_send_buffer_size, + &self.is_data_channel, + ) + } + } + + #[derive(Copy, Clone)] + pub struct OptionsRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> OptionsRef<'a> { + pub fn direct(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "Options", "direct")?.unwrap_or(false), + ) + } + + pub fn max_message_size(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "Options", "max_message_size")? + .unwrap_or(0), + ) + } + + pub fn initial_available_outgoing_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "Options", "initial_available_outgoing_bitrate")? + .unwrap_or(0), + ) + } + + pub fn enable_sctp(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(3, "Options", "enable_sctp")?.unwrap_or(false), + ) + } + + pub fn num_sctp_streams( + &self, + ) -> ::planus::Result< + ::core::option::Option>, + > { + self.0.access(4, "Options", "num_sctp_streams") + } + + pub fn max_sctp_message_size(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(5, "Options", "max_sctp_message_size")? + .unwrap_or(0), + ) + } + + pub fn sctp_send_buffer_size(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(6, "Options", "sctp_send_buffer_size")? + .unwrap_or(0), + ) + } + + pub fn is_data_channel(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(7, "Options", "is_data_channel")? + .unwrap_or(false), + ) + } + } + + impl<'a> ::core::fmt::Debug for OptionsRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("OptionsRef"); + f.field("direct", &self.direct()); + f.field("max_message_size", &self.max_message_size()); + f.field( + "initial_available_outgoing_bitrate", + &self.initial_available_outgoing_bitrate(), + ); + f.field("enable_sctp", &self.enable_sctp()); + if let ::core::option::Option::Some(field_num_sctp_streams) = + self.num_sctp_streams().transpose() + { + f.field("num_sctp_streams", &field_num_sctp_streams); + } + f.field("max_sctp_message_size", &self.max_sctp_message_size()); + f.field("sctp_send_buffer_size", &self.sctp_send_buffer_size()); + f.field("is_data_channel", &self.is_data_channel()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Options { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: OptionsRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + direct: ::core::convert::TryInto::try_into(value.direct()?)?, + max_message_size: ::core::convert::TryInto::try_into( + value.max_message_size()?, + )?, + initial_available_outgoing_bitrate: ::core::convert::TryInto::try_into( + value.initial_available_outgoing_bitrate()?, + )?, + enable_sctp: ::core::convert::TryInto::try_into(value.enable_sctp()?)?, + num_sctp_streams: if let ::core::option::Option::Some(num_sctp_streams) = + value.num_sctp_streams()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(num_sctp_streams)?, + )) + } else { + ::core::option::Option::None + }, + max_sctp_message_size: ::core::convert::TryInto::try_into( + value.max_sctp_message_size()?, + )?, + sctp_send_buffer_size: ::core::convert::TryInto::try_into( + value.sctp_send_buffer_size()?, + )?, + is_data_channel: ::core::convert::TryInto::try_into( + value.is_data_channel()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for OptionsRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for OptionsRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[OptionsRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Options { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for OptionsRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[OptionsRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Stats { + pub transport_id: ::planus::alloc::string::String, + pub timestamp: u64, + pub sctp_state: ::core::option::Option<::planus::alloc::string::String>, + pub bytes_received: u64, + pub recv_bitrate: u64, + pub bytes_sent: u64, + pub send_bitrate: u64, + pub rtp_bytes_received: u64, + pub rtp_recv_bitrate: u64, + pub rtp_bytes_sent: u64, + pub rtp_send_bitrate: u64, + pub rtx_bytes_received: u64, + pub rtx_recv_bitrate: u64, + pub rtx_bytes_sent: u64, + pub rtx_send_bitrate: u64, + pub probation_bytes_sent: u64, + pub probation_send_bitrate: u64, + pub available_outgoing_bitrate: u64, + pub available_incoming_bitrate: u64, + pub max_incoming_bitrate: u64, + pub max_outgoing_bitrate: u64, + pub min_outgoing_bitrate: u64, + pub rtp_packet_loss_received: u64, + pub rtp_packet_loss_sent: u64, + } + + impl Stats { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_transport_id: impl ::planus::WriteAs<::planus::Offset>, + field_timestamp: impl ::planus::WriteAsDefault, + field_sctp_state: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + field_bytes_received: impl ::planus::WriteAsDefault, + field_recv_bitrate: impl ::planus::WriteAsDefault, + field_bytes_sent: impl ::planus::WriteAsDefault, + field_send_bitrate: impl ::planus::WriteAsDefault, + field_rtp_bytes_received: impl ::planus::WriteAsDefault, + field_rtp_recv_bitrate: impl ::planus::WriteAsDefault, + field_rtp_bytes_sent: impl ::planus::WriteAsDefault, + field_rtp_send_bitrate: impl ::planus::WriteAsDefault, + field_rtx_bytes_received: impl ::planus::WriteAsDefault, + field_rtx_recv_bitrate: impl ::planus::WriteAsDefault, + field_rtx_bytes_sent: impl ::planus::WriteAsDefault, + field_rtx_send_bitrate: impl ::planus::WriteAsDefault, + field_probation_bytes_sent: impl ::planus::WriteAsDefault, + field_probation_send_bitrate: impl ::planus::WriteAsDefault, + field_available_outgoing_bitrate: impl ::planus::WriteAsDefault, + field_available_incoming_bitrate: impl ::planus::WriteAsDefault, + field_max_incoming_bitrate: impl ::planus::WriteAsDefault, + field_max_outgoing_bitrate: impl ::planus::WriteAsDefault, + field_min_outgoing_bitrate: impl ::planus::WriteAsDefault, + field_rtp_packet_loss_received: impl ::planus::WriteAsDefault, + field_rtp_packet_loss_sent: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_transport_id = field_transport_id.prepare(builder); + + let prepared_timestamp = field_timestamp.prepare(builder, &0); + + let prepared_sctp_state = field_sctp_state.prepare(builder); + + let prepared_bytes_received = field_bytes_received.prepare(builder, &0); + + let prepared_recv_bitrate = field_recv_bitrate.prepare(builder, &0); + + let prepared_bytes_sent = field_bytes_sent.prepare(builder, &0); + + let prepared_send_bitrate = field_send_bitrate.prepare(builder, &0); + + let prepared_rtp_bytes_received = field_rtp_bytes_received.prepare(builder, &0); + + let prepared_rtp_recv_bitrate = field_rtp_recv_bitrate.prepare(builder, &0); + + let prepared_rtp_bytes_sent = field_rtp_bytes_sent.prepare(builder, &0); + + let prepared_rtp_send_bitrate = field_rtp_send_bitrate.prepare(builder, &0); + + let prepared_rtx_bytes_received = field_rtx_bytes_received.prepare(builder, &0); + + let prepared_rtx_recv_bitrate = field_rtx_recv_bitrate.prepare(builder, &0); + + let prepared_rtx_bytes_sent = field_rtx_bytes_sent.prepare(builder, &0); + + let prepared_rtx_send_bitrate = field_rtx_send_bitrate.prepare(builder, &0); + + let prepared_probation_bytes_sent = + field_probation_bytes_sent.prepare(builder, &0); + + let prepared_probation_send_bitrate = + field_probation_send_bitrate.prepare(builder, &0); + + let prepared_available_outgoing_bitrate = + field_available_outgoing_bitrate.prepare(builder, &0); + + let prepared_available_incoming_bitrate = + field_available_incoming_bitrate.prepare(builder, &0); + + let prepared_max_incoming_bitrate = + field_max_incoming_bitrate.prepare(builder, &0); + + let prepared_max_outgoing_bitrate = + field_max_outgoing_bitrate.prepare(builder, &0); + + let prepared_min_outgoing_bitrate = + field_min_outgoing_bitrate.prepare(builder, &0); + + let prepared_rtp_packet_loss_received = + field_rtp_packet_loss_received.prepare(builder, &0); + + let prepared_rtp_packet_loss_sent = + field_rtp_packet_loss_sent.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<50, 184>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_timestamp.is_some() { + table_writer.calculate_size::(4); + } + if prepared_sctp_state.is_some() { + table_writer.calculate_size::<::planus::Offset>(6); + } + if prepared_bytes_received.is_some() { + table_writer.calculate_size::(8); + } + if prepared_recv_bitrate.is_some() { + table_writer.calculate_size::(10); + } + if prepared_bytes_sent.is_some() { + table_writer.calculate_size::(12); + } + if prepared_send_bitrate.is_some() { + table_writer.calculate_size::(14); + } + if prepared_rtp_bytes_received.is_some() { + table_writer.calculate_size::(16); + } + if prepared_rtp_recv_bitrate.is_some() { + table_writer.calculate_size::(18); + } + if prepared_rtp_bytes_sent.is_some() { + table_writer.calculate_size::(20); + } + if prepared_rtp_send_bitrate.is_some() { + table_writer.calculate_size::(22); + } + if prepared_rtx_bytes_received.is_some() { + table_writer.calculate_size::(24); + } + if prepared_rtx_recv_bitrate.is_some() { + table_writer.calculate_size::(26); + } + if prepared_rtx_bytes_sent.is_some() { + table_writer.calculate_size::(28); + } + if prepared_rtx_send_bitrate.is_some() { + table_writer.calculate_size::(30); + } + if prepared_probation_bytes_sent.is_some() { + table_writer.calculate_size::(32); + } + if prepared_probation_send_bitrate.is_some() { + table_writer.calculate_size::(34); + } + if prepared_available_outgoing_bitrate.is_some() { + table_writer.calculate_size::(36); + } + if prepared_available_incoming_bitrate.is_some() { + table_writer.calculate_size::(38); + } + if prepared_max_incoming_bitrate.is_some() { + table_writer.calculate_size::(40); + } + if prepared_max_outgoing_bitrate.is_some() { + table_writer.calculate_size::(42); + } + if prepared_min_outgoing_bitrate.is_some() { + table_writer.calculate_size::(44); + } + if prepared_rtp_packet_loss_received.is_some() { + table_writer.calculate_size::(46); + } + if prepared_rtp_packet_loss_sent.is_some() { + table_writer.calculate_size::(48); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_timestamp) = prepared_timestamp + { + table_writer.write::<_, _, 8>(1, &prepared_timestamp); + } + if let ::core::option::Option::Some(prepared_bytes_received) = + prepared_bytes_received + { + table_writer.write::<_, _, 8>(3, &prepared_bytes_received); + } + if let ::core::option::Option::Some(prepared_recv_bitrate) = + prepared_recv_bitrate + { + table_writer.write::<_, _, 8>(4, &prepared_recv_bitrate); + } + if let ::core::option::Option::Some(prepared_bytes_sent) = + prepared_bytes_sent + { + table_writer.write::<_, _, 8>(5, &prepared_bytes_sent); + } + if let ::core::option::Option::Some(prepared_send_bitrate) = + prepared_send_bitrate + { + table_writer.write::<_, _, 8>(6, &prepared_send_bitrate); + } + if let ::core::option::Option::Some(prepared_rtp_bytes_received) = + prepared_rtp_bytes_received + { + table_writer.write::<_, _, 8>(7, &prepared_rtp_bytes_received); + } + if let ::core::option::Option::Some(prepared_rtp_recv_bitrate) = + prepared_rtp_recv_bitrate + { + table_writer.write::<_, _, 8>(8, &prepared_rtp_recv_bitrate); + } + if let ::core::option::Option::Some(prepared_rtp_bytes_sent) = + prepared_rtp_bytes_sent + { + table_writer.write::<_, _, 8>(9, &prepared_rtp_bytes_sent); + } + if let ::core::option::Option::Some(prepared_rtp_send_bitrate) = + prepared_rtp_send_bitrate + { + table_writer.write::<_, _, 8>(10, &prepared_rtp_send_bitrate); + } + if let ::core::option::Option::Some(prepared_rtx_bytes_received) = + prepared_rtx_bytes_received + { + table_writer.write::<_, _, 8>(11, &prepared_rtx_bytes_received); + } + if let ::core::option::Option::Some(prepared_rtx_recv_bitrate) = + prepared_rtx_recv_bitrate + { + table_writer.write::<_, _, 8>(12, &prepared_rtx_recv_bitrate); + } + if let ::core::option::Option::Some(prepared_rtx_bytes_sent) = + prepared_rtx_bytes_sent + { + table_writer.write::<_, _, 8>(13, &prepared_rtx_bytes_sent); + } + if let ::core::option::Option::Some(prepared_rtx_send_bitrate) = + prepared_rtx_send_bitrate + { + table_writer.write::<_, _, 8>(14, &prepared_rtx_send_bitrate); + } + if let ::core::option::Option::Some(prepared_probation_bytes_sent) = + prepared_probation_bytes_sent + { + table_writer.write::<_, _, 8>(15, &prepared_probation_bytes_sent); + } + if let ::core::option::Option::Some(prepared_probation_send_bitrate) = + prepared_probation_send_bitrate + { + table_writer.write::<_, _, 8>(16, &prepared_probation_send_bitrate); + } + if let ::core::option::Option::Some(prepared_available_outgoing_bitrate) = + prepared_available_outgoing_bitrate + { + table_writer.write::<_, _, 8>(17, &prepared_available_outgoing_bitrate); + } + if let ::core::option::Option::Some(prepared_available_incoming_bitrate) = + prepared_available_incoming_bitrate + { + table_writer.write::<_, _, 8>(18, &prepared_available_incoming_bitrate); + } + if let ::core::option::Option::Some(prepared_max_incoming_bitrate) = + prepared_max_incoming_bitrate + { + table_writer.write::<_, _, 8>(19, &prepared_max_incoming_bitrate); + } + if let ::core::option::Option::Some(prepared_max_outgoing_bitrate) = + prepared_max_outgoing_bitrate + { + table_writer.write::<_, _, 8>(20, &prepared_max_outgoing_bitrate); + } + if let ::core::option::Option::Some(prepared_min_outgoing_bitrate) = + prepared_min_outgoing_bitrate + { + table_writer.write::<_, _, 8>(21, &prepared_min_outgoing_bitrate); + } + if let ::core::option::Option::Some(prepared_rtp_packet_loss_received) = + prepared_rtp_packet_loss_received + { + table_writer.write::<_, _, 8>(22, &prepared_rtp_packet_loss_received); + } + if let ::core::option::Option::Some(prepared_rtp_packet_loss_sent) = + prepared_rtp_packet_loss_sent + { + table_writer.write::<_, _, 8>(23, &prepared_rtp_packet_loss_sent); + } + table_writer.write::<_, _, 4>(0, &prepared_transport_id); + if let ::core::option::Option::Some(prepared_sctp_state) = + prepared_sctp_state + { + table_writer.write::<_, _, 4>(2, &prepared_sctp_state); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Stats { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Stats { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Stats { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Stats::create( + builder, + &self.transport_id, + &self.timestamp, + &self.sctp_state, + &self.bytes_received, + &self.recv_bitrate, + &self.bytes_sent, + &self.send_bitrate, + &self.rtp_bytes_received, + &self.rtp_recv_bitrate, + &self.rtp_bytes_sent, + &self.rtp_send_bitrate, + &self.rtx_bytes_received, + &self.rtx_recv_bitrate, + &self.rtx_bytes_sent, + &self.rtx_send_bitrate, + &self.probation_bytes_sent, + &self.probation_send_bitrate, + &self.available_outgoing_bitrate, + &self.available_incoming_bitrate, + &self.max_incoming_bitrate, + &self.max_outgoing_bitrate, + &self.min_outgoing_bitrate, + &self.rtp_packet_loss_received, + &self.rtp_packet_loss_sent, + ) + } + } + + #[derive(Copy, Clone)] + pub struct StatsRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> StatsRef<'a> { + pub fn transport_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "Stats", "transport_id") + } + + pub fn timestamp(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(1, "Stats", "timestamp")?.unwrap_or(0)) + } + + pub fn sctp_state( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(2, "Stats", "sctp_state") + } + + pub fn bytes_received(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(3, "Stats", "bytes_received")?.unwrap_or(0), + ) + } + + pub fn recv_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(4, "Stats", "recv_bitrate")?.unwrap_or(0), + ) + } + + pub fn bytes_sent(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(5, "Stats", "bytes_sent")?.unwrap_or(0), + ) + } + + pub fn send_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(6, "Stats", "send_bitrate")?.unwrap_or(0), + ) + } + + pub fn rtp_bytes_received(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(7, "Stats", "rtp_bytes_received")? + .unwrap_or(0), + ) + } + + pub fn rtp_recv_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(8, "Stats", "rtp_recv_bitrate")?.unwrap_or(0), + ) + } + + pub fn rtp_bytes_sent(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(9, "Stats", "rtp_bytes_sent")?.unwrap_or(0), + ) + } + + pub fn rtp_send_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(10, "Stats", "rtp_send_bitrate")?.unwrap_or(0), + ) + } + + pub fn rtx_bytes_received(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(11, "Stats", "rtx_bytes_received")? + .unwrap_or(0), + ) + } + + pub fn rtx_recv_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(12, "Stats", "rtx_recv_bitrate")?.unwrap_or(0), + ) + } + + pub fn rtx_bytes_sent(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(13, "Stats", "rtx_bytes_sent")?.unwrap_or(0), + ) + } + + pub fn rtx_send_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(14, "Stats", "rtx_send_bitrate")?.unwrap_or(0), + ) + } + + pub fn probation_bytes_sent(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(15, "Stats", "probation_bytes_sent")? + .unwrap_or(0), + ) + } + + pub fn probation_send_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(16, "Stats", "probation_send_bitrate")? + .unwrap_or(0), + ) + } + + pub fn available_outgoing_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(17, "Stats", "available_outgoing_bitrate")? + .unwrap_or(0), + ) + } + + pub fn available_incoming_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(18, "Stats", "available_incoming_bitrate")? + .unwrap_or(0), + ) + } + + pub fn max_incoming_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(19, "Stats", "max_incoming_bitrate")? + .unwrap_or(0), + ) + } + + pub fn max_outgoing_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(20, "Stats", "max_outgoing_bitrate")? + .unwrap_or(0), + ) + } + + pub fn min_outgoing_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(21, "Stats", "min_outgoing_bitrate")? + .unwrap_or(0), + ) + } + + pub fn rtp_packet_loss_received(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(22, "Stats", "rtp_packet_loss_received")? + .unwrap_or(0), + ) + } + + pub fn rtp_packet_loss_sent(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(23, "Stats", "rtp_packet_loss_sent")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for StatsRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("StatsRef"); + f.field("transport_id", &self.transport_id()); + f.field("timestamp", &self.timestamp()); + if let ::core::option::Option::Some(field_sctp_state) = + self.sctp_state().transpose() + { + f.field("sctp_state", &field_sctp_state); + } + f.field("bytes_received", &self.bytes_received()); + f.field("recv_bitrate", &self.recv_bitrate()); + f.field("bytes_sent", &self.bytes_sent()); + f.field("send_bitrate", &self.send_bitrate()); + f.field("rtp_bytes_received", &self.rtp_bytes_received()); + f.field("rtp_recv_bitrate", &self.rtp_recv_bitrate()); + f.field("rtp_bytes_sent", &self.rtp_bytes_sent()); + f.field("rtp_send_bitrate", &self.rtp_send_bitrate()); + f.field("rtx_bytes_received", &self.rtx_bytes_received()); + f.field("rtx_recv_bitrate", &self.rtx_recv_bitrate()); + f.field("rtx_bytes_sent", &self.rtx_bytes_sent()); + f.field("rtx_send_bitrate", &self.rtx_send_bitrate()); + f.field("probation_bytes_sent", &self.probation_bytes_sent()); + f.field("probation_send_bitrate", &self.probation_send_bitrate()); + f.field( + "available_outgoing_bitrate", + &self.available_outgoing_bitrate(), + ); + f.field( + "available_incoming_bitrate", + &self.available_incoming_bitrate(), + ); + f.field("max_incoming_bitrate", &self.max_incoming_bitrate()); + f.field("max_outgoing_bitrate", &self.max_outgoing_bitrate()); + f.field("min_outgoing_bitrate", &self.min_outgoing_bitrate()); + f.field("rtp_packet_loss_received", &self.rtp_packet_loss_received()); + f.field("rtp_packet_loss_sent", &self.rtp_packet_loss_sent()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Stats { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: StatsRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + transport_id: ::core::convert::TryInto::try_into(value.transport_id()?)?, + timestamp: ::core::convert::TryInto::try_into(value.timestamp()?)?, + sctp_state: if let ::core::option::Option::Some(sctp_state) = + value.sctp_state()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + sctp_state, + )?) + } else { + ::core::option::Option::None + }, + bytes_received: ::core::convert::TryInto::try_into( + value.bytes_received()?, + )?, + recv_bitrate: ::core::convert::TryInto::try_into(value.recv_bitrate()?)?, + bytes_sent: ::core::convert::TryInto::try_into(value.bytes_sent()?)?, + send_bitrate: ::core::convert::TryInto::try_into(value.send_bitrate()?)?, + rtp_bytes_received: ::core::convert::TryInto::try_into( + value.rtp_bytes_received()?, + )?, + rtp_recv_bitrate: ::core::convert::TryInto::try_into( + value.rtp_recv_bitrate()?, + )?, + rtp_bytes_sent: ::core::convert::TryInto::try_into( + value.rtp_bytes_sent()?, + )?, + rtp_send_bitrate: ::core::convert::TryInto::try_into( + value.rtp_send_bitrate()?, + )?, + rtx_bytes_received: ::core::convert::TryInto::try_into( + value.rtx_bytes_received()?, + )?, + rtx_recv_bitrate: ::core::convert::TryInto::try_into( + value.rtx_recv_bitrate()?, + )?, + rtx_bytes_sent: ::core::convert::TryInto::try_into( + value.rtx_bytes_sent()?, + )?, + rtx_send_bitrate: ::core::convert::TryInto::try_into( + value.rtx_send_bitrate()?, + )?, + probation_bytes_sent: ::core::convert::TryInto::try_into( + value.probation_bytes_sent()?, + )?, + probation_send_bitrate: ::core::convert::TryInto::try_into( + value.probation_send_bitrate()?, + )?, + available_outgoing_bitrate: ::core::convert::TryInto::try_into( + value.available_outgoing_bitrate()?, + )?, + available_incoming_bitrate: ::core::convert::TryInto::try_into( + value.available_incoming_bitrate()?, + )?, + max_incoming_bitrate: ::core::convert::TryInto::try_into( + value.max_incoming_bitrate()?, + )?, + max_outgoing_bitrate: ::core::convert::TryInto::try_into( + value.max_outgoing_bitrate()?, + )?, + min_outgoing_bitrate: ::core::convert::TryInto::try_into( + value.min_outgoing_bitrate()?, + )?, + rtp_packet_loss_received: ::core::convert::TryInto::try_into( + value.rtp_packet_loss_received()?, + )?, + rtp_packet_loss_sent: ::core::convert::TryInto::try_into( + value.rtp_packet_loss_sent()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for StatsRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for StatsRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[StatsRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Stats { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for StatsRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[StatsRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SetMaxIncomingBitrateRequest { + pub max_incoming_bitrate: u32, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for SetMaxIncomingBitrateRequest { + fn default() -> Self { + Self { + max_incoming_bitrate: 0, + } + } + } + + impl SetMaxIncomingBitrateRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_max_incoming_bitrate: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_max_incoming_bitrate = + field_max_incoming_bitrate.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_max_incoming_bitrate.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_max_incoming_bitrate) = + prepared_max_incoming_bitrate + { + table_writer.write::<_, _, 4>(0, &prepared_max_incoming_bitrate); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for SetMaxIncomingBitrateRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for SetMaxIncomingBitrateRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SetMaxIncomingBitrateRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SetMaxIncomingBitrateRequest::create(builder, &self.max_incoming_bitrate) + } + } + + #[derive(Copy, Clone)] + pub struct SetMaxIncomingBitrateRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SetMaxIncomingBitrateRequestRef<'a> { + pub fn max_incoming_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "SetMaxIncomingBitrateRequest", "max_incoming_bitrate")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for SetMaxIncomingBitrateRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SetMaxIncomingBitrateRequestRef"); + f.field("max_incoming_bitrate", &self.max_incoming_bitrate()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for SetMaxIncomingBitrateRequest + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SetMaxIncomingBitrateRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + max_incoming_bitrate: ::core::convert::TryInto::try_into( + value.max_incoming_bitrate()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SetMaxIncomingBitrateRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SetMaxIncomingBitrateRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SetMaxIncomingBitrateRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for SetMaxIncomingBitrateRequest + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SetMaxIncomingBitrateRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[SetMaxIncomingBitrateRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SetMaxOutgoingBitrateRequest { + pub max_outgoing_bitrate: u32, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for SetMaxOutgoingBitrateRequest { + fn default() -> Self { + Self { + max_outgoing_bitrate: 0, + } + } + } + + impl SetMaxOutgoingBitrateRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_max_outgoing_bitrate: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_max_outgoing_bitrate = + field_max_outgoing_bitrate.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_max_outgoing_bitrate.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_max_outgoing_bitrate) = + prepared_max_outgoing_bitrate + { + table_writer.write::<_, _, 4>(0, &prepared_max_outgoing_bitrate); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for SetMaxOutgoingBitrateRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for SetMaxOutgoingBitrateRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SetMaxOutgoingBitrateRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SetMaxOutgoingBitrateRequest::create(builder, &self.max_outgoing_bitrate) + } + } + + #[derive(Copy, Clone)] + pub struct SetMaxOutgoingBitrateRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SetMaxOutgoingBitrateRequestRef<'a> { + pub fn max_outgoing_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "SetMaxOutgoingBitrateRequest", "max_outgoing_bitrate")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for SetMaxOutgoingBitrateRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SetMaxOutgoingBitrateRequestRef"); + f.field("max_outgoing_bitrate", &self.max_outgoing_bitrate()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for SetMaxOutgoingBitrateRequest + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SetMaxOutgoingBitrateRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + max_outgoing_bitrate: ::core::convert::TryInto::try_into( + value.max_outgoing_bitrate()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SetMaxOutgoingBitrateRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SetMaxOutgoingBitrateRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SetMaxOutgoingBitrateRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for SetMaxOutgoingBitrateRequest + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SetMaxOutgoingBitrateRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[SetMaxOutgoingBitrateRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SetMinOutgoingBitrateRequest { + pub min_outgoing_bitrate: u32, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for SetMinOutgoingBitrateRequest { + fn default() -> Self { + Self { + min_outgoing_bitrate: 0, + } + } + } + + impl SetMinOutgoingBitrateRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_min_outgoing_bitrate: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_min_outgoing_bitrate = + field_min_outgoing_bitrate.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_min_outgoing_bitrate.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_min_outgoing_bitrate) = + prepared_min_outgoing_bitrate + { + table_writer.write::<_, _, 4>(0, &prepared_min_outgoing_bitrate); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for SetMinOutgoingBitrateRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for SetMinOutgoingBitrateRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SetMinOutgoingBitrateRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SetMinOutgoingBitrateRequest::create(builder, &self.min_outgoing_bitrate) + } + } + + #[derive(Copy, Clone)] + pub struct SetMinOutgoingBitrateRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SetMinOutgoingBitrateRequestRef<'a> { + pub fn min_outgoing_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "SetMinOutgoingBitrateRequest", "min_outgoing_bitrate")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for SetMinOutgoingBitrateRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SetMinOutgoingBitrateRequestRef"); + f.field("min_outgoing_bitrate", &self.min_outgoing_bitrate()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for SetMinOutgoingBitrateRequest + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SetMinOutgoingBitrateRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + min_outgoing_bitrate: ::core::convert::TryInto::try_into( + value.min_outgoing_bitrate()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SetMinOutgoingBitrateRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SetMinOutgoingBitrateRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SetMinOutgoingBitrateRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for SetMinOutgoingBitrateRequest + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SetMinOutgoingBitrateRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[SetMinOutgoingBitrateRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct EnableTraceEventRequest { + pub events: ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + } + + impl EnableTraceEventRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_events: impl ::planus::WriteAs<::planus::Offset<[::planus::Offset]>>, + ) -> ::planus::Offset { + let prepared_events = field_events.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_events); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for EnableTraceEventRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for EnableTraceEventRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for EnableTraceEventRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + EnableTraceEventRequest::create(builder, &self.events) + } + } + + #[derive(Copy, Clone)] + pub struct EnableTraceEventRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> EnableTraceEventRequestRef<'a> { + pub fn events( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + > { + self.0 + .access_required(0, "EnableTraceEventRequest", "events") + } + } + + impl<'a> ::core::fmt::Debug for EnableTraceEventRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("EnableTraceEventRequestRef"); + f.field("events", &self.events()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for EnableTraceEventRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: EnableTraceEventRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + events: value.events()?.to_vec_result()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for EnableTraceEventRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for EnableTraceEventRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[EnableTraceEventRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for EnableTraceEventRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for EnableTraceEventRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[EnableTraceEventRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CloseProducerRequest { + pub producer_id: ::planus::alloc::string::String, + } + + impl CloseProducerRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_producer_id: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_producer_id = field_producer_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_producer_id); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for CloseProducerRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for CloseProducerRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CloseProducerRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CloseProducerRequest::create(builder, &self.producer_id) + } + } + + #[derive(Copy, Clone)] + pub struct CloseProducerRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CloseProducerRequestRef<'a> { + pub fn producer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "CloseProducerRequest", "producer_id") + } + } + + impl<'a> ::core::fmt::Debug for CloseProducerRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CloseProducerRequestRef"); + f.field("producer_id", &self.producer_id()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for CloseProducerRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: CloseProducerRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + producer_id: ::core::convert::TryInto::try_into(value.producer_id()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CloseProducerRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CloseProducerRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CloseProducerRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for CloseProducerRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CloseProducerRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[CloseProducerRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CloseConsumerRequest { + pub consumer_id: ::planus::alloc::string::String, + } + + impl CloseConsumerRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_consumer_id: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_consumer_id = field_consumer_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_consumer_id); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for CloseConsumerRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for CloseConsumerRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CloseConsumerRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CloseConsumerRequest::create(builder, &self.consumer_id) + } + } + + #[derive(Copy, Clone)] + pub struct CloseConsumerRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CloseConsumerRequestRef<'a> { + pub fn consumer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "CloseConsumerRequest", "consumer_id") + } + } + + impl<'a> ::core::fmt::Debug for CloseConsumerRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CloseConsumerRequestRef"); + f.field("consumer_id", &self.consumer_id()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for CloseConsumerRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: CloseConsumerRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + consumer_id: ::core::convert::TryInto::try_into(value.consumer_id()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CloseConsumerRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CloseConsumerRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CloseConsumerRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for CloseConsumerRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CloseConsumerRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[CloseConsumerRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CloseDataProducerRequest { + pub data_producer_id: ::planus::alloc::string::String, + } + + impl CloseDataProducerRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_data_producer_id: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_data_producer_id = field_data_producer_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_data_producer_id); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for CloseDataProducerRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for CloseDataProducerRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CloseDataProducerRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CloseDataProducerRequest::create(builder, &self.data_producer_id) + } + } + + #[derive(Copy, Clone)] + pub struct CloseDataProducerRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CloseDataProducerRequestRef<'a> { + pub fn data_producer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "CloseDataProducerRequest", "data_producer_id") + } + } + + impl<'a> ::core::fmt::Debug for CloseDataProducerRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CloseDataProducerRequestRef"); + f.field("data_producer_id", &self.data_producer_id()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for CloseDataProducerRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: CloseDataProducerRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + data_producer_id: ::core::convert::TryInto::try_into( + value.data_producer_id()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CloseDataProducerRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CloseDataProducerRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CloseDataProducerRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for CloseDataProducerRequest + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CloseDataProducerRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[CloseDataProducerRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CloseDataConsumerRequest { + pub data_consumer_id: ::planus::alloc::string::String, + } + + impl CloseDataConsumerRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_data_consumer_id: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_data_consumer_id = field_data_consumer_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_data_consumer_id); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for CloseDataConsumerRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for CloseDataConsumerRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CloseDataConsumerRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CloseDataConsumerRequest::create(builder, &self.data_consumer_id) + } + } + + #[derive(Copy, Clone)] + pub struct CloseDataConsumerRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CloseDataConsumerRequestRef<'a> { + pub fn data_consumer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "CloseDataConsumerRequest", "data_consumer_id") + } + } + + impl<'a> ::core::fmt::Debug for CloseDataConsumerRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CloseDataConsumerRequestRef"); + f.field("data_consumer_id", &self.data_consumer_id()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for CloseDataConsumerRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: CloseDataConsumerRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + data_consumer_id: ::core::convert::TryInto::try_into( + value.data_consumer_id()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CloseDataConsumerRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CloseDataConsumerRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CloseDataConsumerRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for CloseDataConsumerRequest + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CloseDataConsumerRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[CloseDataConsumerRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SendRtcpNotification { + pub data: ::planus::alloc::vec::Vec, + } + + impl SendRtcpNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_data: impl ::planus::WriteAs<::planus::Offset<[u8]>>, + ) -> ::planus::Offset { + let prepared_data = field_data.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset<[u8]>>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_data); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for SendRtcpNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for SendRtcpNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SendRtcpNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SendRtcpNotification::create(builder, &self.data) + } + } + + #[derive(Copy, Clone)] + pub struct SendRtcpNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SendRtcpNotificationRef<'a> { + pub fn data(&self) -> ::planus::Result<::planus::Vector<'a, u8>> { + self.0.access_required(0, "SendRtcpNotification", "data") + } + } + + impl<'a> ::core::fmt::Debug for SendRtcpNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SendRtcpNotificationRef"); + f.field("data", &self.data()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for SendRtcpNotification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SendRtcpNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + data: value.data()?.to_vec()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SendRtcpNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SendRtcpNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SendRtcpNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for SendRtcpNotification { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SendRtcpNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[SendRtcpNotificationRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SctpStateChangeNotification { + pub sctp_state: super::sctp_association::SctpState, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for SctpStateChangeNotification { + fn default() -> Self { + Self { + sctp_state: super::sctp_association::SctpState::New, + } + } + } + + impl SctpStateChangeNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_sctp_state: impl ::planus::WriteAsDefault< + super::sctp_association::SctpState, + super::sctp_association::SctpState, + >, + ) -> ::planus::Offset { + let prepared_sctp_state = + field_sctp_state.prepare(builder, &super::sctp_association::SctpState::New); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 1>::new(builder); + + if prepared_sctp_state.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_sctp_state) = + prepared_sctp_state + { + table_writer.write::<_, _, 1>(0, &prepared_sctp_state); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for SctpStateChangeNotification + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for SctpStateChangeNotification + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SctpStateChangeNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SctpStateChangeNotification::create(builder, &self.sctp_state) + } + } + + #[derive(Copy, Clone)] + pub struct SctpStateChangeNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SctpStateChangeNotificationRef<'a> { + pub fn sctp_state(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "SctpStateChangeNotification", "sctp_state")? + .unwrap_or(super::sctp_association::SctpState::New), + ) + } + } + + impl<'a> ::core::fmt::Debug for SctpStateChangeNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SctpStateChangeNotificationRef"); + f.field("sctp_state", &self.sctp_state()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for SctpStateChangeNotification + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SctpStateChangeNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + sctp_state: ::core::convert::TryInto::try_into(value.sctp_state()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SctpStateChangeNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SctpStateChangeNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SctpStateChangeNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for SctpStateChangeNotification + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SctpStateChangeNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[SctpStateChangeNotificationRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum TraceType { + Probation = 0, + Bwe = 1, + } + + impl ::core::convert::TryFrom for TraceType { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 0 => ::core::result::Result::Ok(TraceType::Probation), + 1 => ::core::result::Result::Ok(TraceType::Bwe), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: TraceType) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for TraceType { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for TraceType { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for TraceType { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> TraceType { + *self + } + } + + impl ::planus::WriteAsDefault for TraceType { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &TraceType, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for TraceType { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for TraceType { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for TraceType { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "TraceType", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for TraceType { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum TraceDirection { + DirectionIn = 0, + DirectionOut = 1, + } + + impl ::core::convert::TryFrom for TraceDirection { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 0 => ::core::result::Result::Ok(TraceDirection::DirectionIn), + 1 => ::core::result::Result::Ok(TraceDirection::DirectionOut), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: TraceDirection) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for TraceDirection { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for TraceDirection { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for TraceDirection { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> TraceDirection { + *self + } + } + + impl ::planus::WriteAsDefault for TraceDirection { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &TraceDirection, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for TraceDirection { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for TraceDirection { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for TraceDirection { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "TraceDirection", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for TraceDirection { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub enum TraceInfo { + BweTraceInfo(::planus::alloc::boxed::Box), + } + + impl TraceInfo { + pub fn create_bwe_trace_info( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(1, value.prepare(builder).downcast()) + } + } + + impl ::planus::WriteAsUnion for TraceInfo { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::UnionOffset { + match self { + Self::BweTraceInfo(value) => Self::create_bwe_trace_info(builder, value), + } + } + } + + impl ::planus::WriteAsOptionalUnion for TraceInfo { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::UnionOffset> { + ::core::option::Option::Some(::planus::WriteAsUnion::prepare(self, builder)) + } + } + + #[derive(Copy, Clone, Debug)] + pub enum TraceInfoRef<'a> { + BweTraceInfo(self::BweTraceInfoRef<'a>), + } + + impl<'a> ::core::convert::TryFrom> for TraceInfo { + type Error = ::planus::Error; + + fn try_from(value: TraceInfoRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(match value { + TraceInfoRef::BweTraceInfo(value) => { + TraceInfo::BweTraceInfo(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + }) + } + } + + impl<'a> ::planus::TableReadUnion<'a> for TraceInfoRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + field_offset: usize, + tag: u8, + ) -> ::core::result::Result { + match tag { + 1 => ::core::result::Result::Ok(Self::BweTraceInfo( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + _ => ::core::result::Result::Err( + ::planus::errors::ErrorKind::UnknownUnionTag { tag }, + ), + } + } + } + + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum BweType { + TransportCc = 0, + Remb = 1, + } + + impl ::core::convert::TryFrom for BweType { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 0 => ::core::result::Result::Ok(BweType::TransportCc), + 1 => ::core::result::Result::Ok(BweType::Remb), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: BweType) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for BweType { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for BweType { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for BweType { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> BweType { + *self + } + } + + impl ::planus::WriteAsDefault for BweType { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &BweType, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for BweType { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for BweType { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for BweType { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "BweType", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for BweType { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct BweTraceInfo { + pub desired_bitrate: u32, + pub effective_desired_bitrate: u32, + pub min_bitrate: u32, + pub max_bitrate: u32, + pub start_bitrate: u32, + pub max_padding_bitrate: u32, + pub available_bitrate: u32, + pub bwe_type: self::BweType, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for BweTraceInfo { + fn default() -> Self { + Self { + desired_bitrate: 0, + effective_desired_bitrate: 0, + min_bitrate: 0, + max_bitrate: 0, + start_bitrate: 0, + max_padding_bitrate: 0, + available_bitrate: 0, + bwe_type: self::BweType::TransportCc, + } + } + } + + impl BweTraceInfo { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_desired_bitrate: impl ::planus::WriteAsDefault, + field_effective_desired_bitrate: impl ::planus::WriteAsDefault, + field_min_bitrate: impl ::planus::WriteAsDefault, + field_max_bitrate: impl ::planus::WriteAsDefault, + field_start_bitrate: impl ::planus::WriteAsDefault, + field_max_padding_bitrate: impl ::planus::WriteAsDefault, + field_available_bitrate: impl ::planus::WriteAsDefault, + field_bwe_type: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_desired_bitrate = field_desired_bitrate.prepare(builder, &0); + + let prepared_effective_desired_bitrate = + field_effective_desired_bitrate.prepare(builder, &0); + + let prepared_min_bitrate = field_min_bitrate.prepare(builder, &0); + + let prepared_max_bitrate = field_max_bitrate.prepare(builder, &0); + + let prepared_start_bitrate = field_start_bitrate.prepare(builder, &0); + + let prepared_max_padding_bitrate = + field_max_padding_bitrate.prepare(builder, &0); + + let prepared_available_bitrate = field_available_bitrate.prepare(builder, &0); + + let prepared_bwe_type = + field_bwe_type.prepare(builder, &self::BweType::TransportCc); + + let mut table_writer = + ::planus::table_writer::TableWriter::<18, 29>::new(builder); + + if prepared_desired_bitrate.is_some() { + table_writer.calculate_size::(2); + } + if prepared_effective_desired_bitrate.is_some() { + table_writer.calculate_size::(4); + } + if prepared_min_bitrate.is_some() { + table_writer.calculate_size::(6); + } + if prepared_max_bitrate.is_some() { + table_writer.calculate_size::(8); + } + if prepared_start_bitrate.is_some() { + table_writer.calculate_size::(10); + } + if prepared_max_padding_bitrate.is_some() { + table_writer.calculate_size::(12); + } + if prepared_available_bitrate.is_some() { + table_writer.calculate_size::(14); + } + if prepared_bwe_type.is_some() { + table_writer.calculate_size::(16); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_desired_bitrate) = + prepared_desired_bitrate + { + table_writer.write::<_, _, 4>(0, &prepared_desired_bitrate); + } + if let ::core::option::Option::Some(prepared_effective_desired_bitrate) = + prepared_effective_desired_bitrate + { + table_writer.write::<_, _, 4>(1, &prepared_effective_desired_bitrate); + } + if let ::core::option::Option::Some(prepared_min_bitrate) = + prepared_min_bitrate + { + table_writer.write::<_, _, 4>(2, &prepared_min_bitrate); + } + if let ::core::option::Option::Some(prepared_max_bitrate) = + prepared_max_bitrate + { + table_writer.write::<_, _, 4>(3, &prepared_max_bitrate); + } + if let ::core::option::Option::Some(prepared_start_bitrate) = + prepared_start_bitrate + { + table_writer.write::<_, _, 4>(4, &prepared_start_bitrate); + } + if let ::core::option::Option::Some(prepared_max_padding_bitrate) = + prepared_max_padding_bitrate + { + table_writer.write::<_, _, 4>(5, &prepared_max_padding_bitrate); + } + if let ::core::option::Option::Some(prepared_available_bitrate) = + prepared_available_bitrate + { + table_writer.write::<_, _, 4>(6, &prepared_available_bitrate); + } + if let ::core::option::Option::Some(prepared_bwe_type) = prepared_bwe_type { + table_writer.write::<_, _, 1>(7, &prepared_bwe_type); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for BweTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for BweTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for BweTraceInfo { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + BweTraceInfo::create( + builder, + &self.desired_bitrate, + &self.effective_desired_bitrate, + &self.min_bitrate, + &self.max_bitrate, + &self.start_bitrate, + &self.max_padding_bitrate, + &self.available_bitrate, + &self.bwe_type, + ) + } + } + + #[derive(Copy, Clone)] + pub struct BweTraceInfoRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> BweTraceInfoRef<'a> { + pub fn desired_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "BweTraceInfo", "desired_bitrate")? + .unwrap_or(0), + ) + } + + pub fn effective_desired_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "BweTraceInfo", "effective_desired_bitrate")? + .unwrap_or(0), + ) + } + + pub fn min_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "BweTraceInfo", "min_bitrate")? + .unwrap_or(0), + ) + } + + pub fn max_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(3, "BweTraceInfo", "max_bitrate")? + .unwrap_or(0), + ) + } + + pub fn start_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(4, "BweTraceInfo", "start_bitrate")? + .unwrap_or(0), + ) + } + + pub fn max_padding_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(5, "BweTraceInfo", "max_padding_bitrate")? + .unwrap_or(0), + ) + } + + pub fn available_bitrate(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(6, "BweTraceInfo", "available_bitrate")? + .unwrap_or(0), + ) + } + + pub fn bwe_type(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(7, "BweTraceInfo", "bwe_type")? + .unwrap_or(self::BweType::TransportCc), + ) + } + } + + impl<'a> ::core::fmt::Debug for BweTraceInfoRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("BweTraceInfoRef"); + f.field("desired_bitrate", &self.desired_bitrate()); + f.field( + "effective_desired_bitrate", + &self.effective_desired_bitrate(), + ); + f.field("min_bitrate", &self.min_bitrate()); + f.field("max_bitrate", &self.max_bitrate()); + f.field("start_bitrate", &self.start_bitrate()); + f.field("max_padding_bitrate", &self.max_padding_bitrate()); + f.field("available_bitrate", &self.available_bitrate()); + f.field("bwe_type", &self.bwe_type()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for BweTraceInfo { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: BweTraceInfoRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + desired_bitrate: ::core::convert::TryInto::try_into( + value.desired_bitrate()?, + )?, + effective_desired_bitrate: ::core::convert::TryInto::try_into( + value.effective_desired_bitrate()?, + )?, + min_bitrate: ::core::convert::TryInto::try_into(value.min_bitrate()?)?, + max_bitrate: ::core::convert::TryInto::try_into(value.max_bitrate()?)?, + start_bitrate: ::core::convert::TryInto::try_into(value.start_bitrate()?)?, + max_padding_bitrate: ::core::convert::TryInto::try_into( + value.max_padding_bitrate()?, + )?, + available_bitrate: ::core::convert::TryInto::try_into( + value.available_bitrate()?, + )?, + bwe_type: ::core::convert::TryInto::try_into(value.bwe_type()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for BweTraceInfoRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for BweTraceInfoRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[BweTraceInfoRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for BweTraceInfo { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for BweTraceInfoRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[BweTraceInfoRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct TraceNotification { + pub type_: self::TraceType, + pub timestamp: u64, + pub direction: self::TraceDirection, + pub info: ::core::option::Option, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for TraceNotification { + fn default() -> Self { + Self { + type_: self::TraceType::Probation, + timestamp: 0, + direction: self::TraceDirection::DirectionIn, + info: ::core::default::Default::default(), + } + } + } + + impl TraceNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_type_: impl ::planus::WriteAsDefault, + field_timestamp: impl ::planus::WriteAsDefault, + field_direction: impl ::planus::WriteAsDefault< + self::TraceDirection, + self::TraceDirection, + >, + field_info: impl ::planus::WriteAsOptionalUnion, + ) -> ::planus::Offset { + let prepared_type_ = field_type_.prepare(builder, &self::TraceType::Probation); + + let prepared_timestamp = field_timestamp.prepare(builder, &0); + + let prepared_direction = + field_direction.prepare(builder, &self::TraceDirection::DirectionIn); + + let prepared_info = field_info.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<10, 15>::new(builder); + + if prepared_type_.is_some() { + table_writer.calculate_size::(2); + } + if prepared_timestamp.is_some() { + table_writer.calculate_size::(4); + } + if prepared_direction.is_some() { + table_writer.calculate_size::(6); + } + if prepared_info.is_some() { + table_writer.calculate_size::(8); + table_writer.calculate_size::<::planus::Offset>(10); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_timestamp) = prepared_timestamp + { + table_writer.write::<_, _, 8>(1, &prepared_timestamp); + } + if let ::core::option::Option::Some(prepared_info) = prepared_info { + table_writer.write::<_, _, 4>(4, &prepared_info.offset()); + } + if let ::core::option::Option::Some(prepared_type_) = prepared_type_ { + table_writer.write::<_, _, 1>(0, &prepared_type_); + } + if let ::core::option::Option::Some(prepared_direction) = prepared_direction + { + table_writer.write::<_, _, 1>(2, &prepared_direction); + } + if let ::core::option::Option::Some(prepared_info) = prepared_info { + table_writer.write::<_, _, 1>(3, &prepared_info.tag()); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for TraceNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for TraceNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for TraceNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + TraceNotification::create( + builder, + &self.type_, + &self.timestamp, + &self.direction, + &self.info, + ) + } + } + + #[derive(Copy, Clone)] + pub struct TraceNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> TraceNotificationRef<'a> { + pub fn type_(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "TraceNotification", "type_")? + .unwrap_or(self::TraceType::Probation), + ) + } + + pub fn timestamp(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "TraceNotification", "timestamp")? + .unwrap_or(0), + ) + } + + pub fn direction(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "TraceNotification", "direction")? + .unwrap_or(self::TraceDirection::DirectionIn), + ) + } + + pub fn info( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access_union(3, "TraceNotification", "info") + } + } + + impl<'a> ::core::fmt::Debug for TraceNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("TraceNotificationRef"); + f.field("type_", &self.type_()); + f.field("timestamp", &self.timestamp()); + f.field("direction", &self.direction()); + if let ::core::option::Option::Some(field_info) = self.info().transpose() { + f.field("info", &field_info); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for TraceNotification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: TraceNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + type_: ::core::convert::TryInto::try_into(value.type_()?)?, + timestamp: ::core::convert::TryInto::try_into(value.timestamp()?)?, + direction: ::core::convert::TryInto::try_into(value.direction()?)?, + info: if let ::core::option::Option::Some(info) = value.info()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(info)?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for TraceNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for TraceNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[TraceNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for TraceNotification { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for TraceNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[TraceNotificationRef]", "read_as_root", 0) + }) + } + } + } + pub mod sctp_association { + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum SctpState { + New = 0, + Connecting = 1, + Connected = 2, + Failed = 3, + Closed = 4, + } + + impl ::core::convert::TryFrom for SctpState { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 0 => ::core::result::Result::Ok(SctpState::New), + 1 => ::core::result::Result::Ok(SctpState::Connecting), + 2 => ::core::result::Result::Ok(SctpState::Connected), + 3 => ::core::result::Result::Ok(SctpState::Failed), + 4 => ::core::result::Result::Ok(SctpState::Closed), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: SctpState) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for SctpState { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for SctpState { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for SctpState { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> SctpState { + *self + } + } + + impl ::planus::WriteAsDefault for SctpState { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &SctpState, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for SctpState { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for SctpState { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for SctpState { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "SctpState", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for SctpState { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + } + pub mod log { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Log { + pub data: ::planus::alloc::string::String, + } + + impl Log { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_data: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_data = field_data.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_data); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Log { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Log { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Log { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Log::create(builder, &self.data) + } + } + + #[derive(Copy, Clone)] + pub struct LogRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> LogRef<'a> { + pub fn data(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "Log", "data") + } + } + + impl<'a> ::core::fmt::Debug for LogRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("LogRef"); + f.field("data", &self.data()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Log { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: LogRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + data: ::core::convert::TryInto::try_into(value.data()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for LogRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for LogRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location("[LogRef]", "get", buffer.offset_from_start) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Log { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for LogRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[LogRef]", "read_as_root", 0) + }) + } + } + } + pub mod message { + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum Type { + Request = 0, + Response = 1, + Notification = 2, + Log = 3, + } + + impl ::core::convert::TryFrom for Type { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 0 => ::core::result::Result::Ok(Type::Request), + 1 => ::core::result::Result::Ok(Type::Response), + 2 => ::core::result::Result::Ok(Type::Notification), + 3 => ::core::result::Result::Ok(Type::Log), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: Type) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for Type { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for Type { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for Type { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> Type { + *self + } + } + + impl ::planus::WriteAsDefault for Type { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &Type, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for Type { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for Type { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for Type { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "Type", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for Type { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub enum Body { + Request(::planus::alloc::boxed::Box), + Response(::planus::alloc::boxed::Box), + Notification(::planus::alloc::boxed::Box), + Log(::planus::alloc::boxed::Box), + } + + impl Body { + pub fn create_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(1, value.prepare(builder).downcast()) + } + + pub fn create_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(2, value.prepare(builder).downcast()) + } + + pub fn create_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(3, value.prepare(builder).downcast()) + } + + pub fn create_log( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(4, value.prepare(builder).downcast()) + } + } + + impl ::planus::WriteAsUnion for Body { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::UnionOffset { + match self { + Self::Request(value) => Self::create_request(builder, value), + Self::Response(value) => Self::create_response(builder, value), + Self::Notification(value) => Self::create_notification(builder, value), + Self::Log(value) => Self::create_log(builder, value), + } + } + } + + impl ::planus::WriteAsOptionalUnion for Body { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::UnionOffset> { + ::core::option::Option::Some(::planus::WriteAsUnion::prepare(self, builder)) + } + } + + #[derive(Copy, Clone, Debug)] + pub enum BodyRef<'a> { + Request(super::request::RequestRef<'a>), + Response(super::response::ResponseRef<'a>), + Notification(super::notification::NotificationRef<'a>), + Log(super::log::LogRef<'a>), + } + + impl<'a> ::core::convert::TryFrom> for Body { + type Error = ::planus::Error; + + fn try_from(value: BodyRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(match value { + BodyRef::Request(value) => Body::Request(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )), + + BodyRef::Response(value) => { + Body::Response(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::Notification(value) => { + Body::Notification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::Log(value) => Body::Log(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )), + }) + } + } + + impl<'a> ::planus::TableReadUnion<'a> for BodyRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + field_offset: usize, + tag: u8, + ) -> ::core::result::Result { + match tag { + 1 => ::core::result::Result::Ok(Self::Request( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 2 => ::core::result::Result::Ok(Self::Response( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 3 => ::core::result::Result::Ok(Self::Notification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 4 => ::core::result::Result::Ok(Self::Log( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + _ => ::core::result::Result::Err( + ::planus::errors::ErrorKind::UnknownUnionTag { tag }, + ), + } + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct Message { + pub type_: self::Type, + pub data: self::Body, + } + + impl Message { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_type_: impl ::planus::WriteAsDefault, + field_data: impl ::planus::WriteAsUnion, + ) -> ::planus::Offset { + let prepared_type_ = field_type_.prepare(builder, &self::Type::Request); + + let prepared_data = field_data.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 6>::new(builder); + + if prepared_type_.is_some() { + table_writer.calculate_size::(2); + } + table_writer.calculate_size::(4); + table_writer.calculate_size::<::planus::Offset>(6); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(2, &prepared_data.offset()); + if let ::core::option::Option::Some(prepared_type_) = prepared_type_ { + table_writer.write::<_, _, 1>(0, &prepared_type_); + } + table_writer.write::<_, _, 1>(1, &prepared_data.tag()); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Message { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Message { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Message { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Message::create(builder, &self.type_, &self.data) + } + } + + #[derive(Copy, Clone)] + pub struct MessageRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> MessageRef<'a> { + pub fn type_(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "Message", "type_")? + .unwrap_or(self::Type::Request), + ) + } + + pub fn data(&self) -> ::planus::Result> { + self.0.access_union_required(1, "Message", "data") + } + } + + impl<'a> ::core::fmt::Debug for MessageRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("MessageRef"); + f.field("type_", &self.type_()); + f.field("data", &self.data()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Message { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: MessageRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + type_: ::core::convert::TryInto::try_into(value.type_()?)?, + data: ::core::convert::TryInto::try_into(value.data()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for MessageRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for MessageRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[MessageRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Message { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for MessageRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[MessageRef]", "read_as_root", 0) + }) + } + } + } + pub mod notification { + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum Event { + TransportSendRtcp = 0, + ProducerSend = 1, + DataProducerSend = 2, + WorkerRunning = 3, + TransportSctpStateChange = 4, + TransportTrace = 5, + WebrtctransportIceSelectedTupleChange = 6, + WebrtctransportIceStateChange = 7, + WebrtctransportDtlsStateChange = 8, + PlaintransportTuple = 9, + PlaintransportRtcpTuple = 10, + DirecttransportRtcp = 11, + ProducerScore = 12, + ProducerTrace = 13, + ProducerVideoOrientationChange = 14, + ConsumerProducerPause = 15, + ConsumerProducerResume = 16, + ConsumerProducerClose = 17, + ConsumerLayersChange = 18, + ConsumerRtp = 19, + ConsumerScore = 20, + ConsumerTrace = 21, + DataconsumerBufferedAmountLow = 22, + DataconsumerSctpSendbufferFull = 23, + DataconsumerDataproducerClose = 24, + DataconsumerMessage = 25, + ActivespeakerobserverDominantSpeaker = 26, + AudiolevelobserverSilence = 27, + AudiolevelobserverVolumes = 28, + } + + impl ::core::convert::TryFrom for Event { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 0 => ::core::result::Result::Ok(Event::TransportSendRtcp), + 1 => ::core::result::Result::Ok(Event::ProducerSend), + 2 => ::core::result::Result::Ok(Event::DataProducerSend), + 3 => ::core::result::Result::Ok(Event::WorkerRunning), + 4 => ::core::result::Result::Ok(Event::TransportSctpStateChange), + 5 => ::core::result::Result::Ok(Event::TransportTrace), + 6 => { + ::core::result::Result::Ok(Event::WebrtctransportIceSelectedTupleChange) + } + 7 => ::core::result::Result::Ok(Event::WebrtctransportIceStateChange), + 8 => ::core::result::Result::Ok(Event::WebrtctransportDtlsStateChange), + 9 => ::core::result::Result::Ok(Event::PlaintransportTuple), + 10 => ::core::result::Result::Ok(Event::PlaintransportRtcpTuple), + 11 => ::core::result::Result::Ok(Event::DirecttransportRtcp), + 12 => ::core::result::Result::Ok(Event::ProducerScore), + 13 => ::core::result::Result::Ok(Event::ProducerTrace), + 14 => ::core::result::Result::Ok(Event::ProducerVideoOrientationChange), + 15 => ::core::result::Result::Ok(Event::ConsumerProducerPause), + 16 => ::core::result::Result::Ok(Event::ConsumerProducerResume), + 17 => ::core::result::Result::Ok(Event::ConsumerProducerClose), + 18 => ::core::result::Result::Ok(Event::ConsumerLayersChange), + 19 => ::core::result::Result::Ok(Event::ConsumerRtp), + 20 => ::core::result::Result::Ok(Event::ConsumerScore), + 21 => ::core::result::Result::Ok(Event::ConsumerTrace), + 22 => ::core::result::Result::Ok(Event::DataconsumerBufferedAmountLow), + 23 => ::core::result::Result::Ok(Event::DataconsumerSctpSendbufferFull), + 24 => ::core::result::Result::Ok(Event::DataconsumerDataproducerClose), + 25 => ::core::result::Result::Ok(Event::DataconsumerMessage), + 26 => { + ::core::result::Result::Ok(Event::ActivespeakerobserverDominantSpeaker) + } + 27 => ::core::result::Result::Ok(Event::AudiolevelobserverSilence), + 28 => ::core::result::Result::Ok(Event::AudiolevelobserverVolumes), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: Event) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for Event { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for Event { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for Event { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> Event { + *self + } + } + + impl ::planus::WriteAsDefault for Event { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &Event, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for Event { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for Event { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for Event { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "Event", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for Event { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub enum Body { + SendRtcpNotification( + ::planus::alloc::boxed::Box, + ), + SctpStateChangeNotification( + ::planus::alloc::boxed::Box, + ), + SendNotification( + ::planus::alloc::boxed::Box, + ), + TraceNotification(::planus::alloc::boxed::Box), + IceSelectedTupleChangeNotification( + ::planus::alloc::boxed::Box< + super::web_rtc_transport::IceSelectedTupleChangeNotification, + >, + ), + IceStateChangeNotification( + ::planus::alloc::boxed::Box< + super::web_rtc_transport::IceStateChangeNotification, + >, + ), + DtlsStateChangeNotification( + ::planus::alloc::boxed::Box< + super::web_rtc_transport::DtlsStateChangeNotification, + >, + ), + TupleNotification( + ::planus::alloc::boxed::Box, + ), + RtcpTupleNotification( + ::planus::alloc::boxed::Box, + ), + RtcpNotification( + ::planus::alloc::boxed::Box, + ), + ScoreNotification(::planus::alloc::boxed::Box), + VideoOrientationChangeNotification( + ::planus::alloc::boxed::Box< + super::producer::VideoOrientationChangeNotification, + >, + ), + LayersChangeNotification( + ::planus::alloc::boxed::Box, + ), + RtpNotification(::planus::alloc::boxed::Box), + MessageNotification( + ::planus::alloc::boxed::Box, + ), + BufferedAmountLowNotification( + ::planus::alloc::boxed::Box< + super::data_consumer::BufferedAmountLowNotification, + >, + ), + DominantSpeakerNotification( + ::planus::alloc::boxed::Box< + super::active_speaker_observer::DominantSpeakerNotification, + >, + ), + VolumesNotification( + ::planus::alloc::boxed::Box, + ), + } + + impl Body { + pub fn create_send_rtcp_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(1, value.prepare(builder).downcast()) + } + + pub fn create_sctp_state_change_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(2, value.prepare(builder).downcast()) + } + + pub fn create_send_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(3, value.prepare(builder).downcast()) + } + + pub fn create_trace_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(4, value.prepare(builder).downcast()) + } + + pub fn create_ice_selected_tuple_change_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset< + super::web_rtc_transport::IceSelectedTupleChangeNotification, + >, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(5, value.prepare(builder).downcast()) + } + + pub fn create_ice_state_change_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset< + super::web_rtc_transport::IceStateChangeNotification, + >, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(6, value.prepare(builder).downcast()) + } + + pub fn create_dtls_state_change_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset< + super::web_rtc_transport::DtlsStateChangeNotification, + >, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(7, value.prepare(builder).downcast()) + } + + pub fn create_tuple_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(8, value.prepare(builder).downcast()) + } + + pub fn create_rtcp_tuple_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(9, value.prepare(builder).downcast()) + } + + pub fn create_rtcp_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(10, value.prepare(builder).downcast()) + } + + pub fn create_score_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(11, value.prepare(builder).downcast()) + } + + pub fn create_video_orientation_change_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset< + super::producer::VideoOrientationChangeNotification, + >, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(12, value.prepare(builder).downcast()) + } + + pub fn create_layers_change_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(13, value.prepare(builder).downcast()) + } + + pub fn create_rtp_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(14, value.prepare(builder).downcast()) + } + + pub fn create_message_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(15, value.prepare(builder).downcast()) + } + + pub fn create_buffered_amount_low_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset< + super::data_consumer::BufferedAmountLowNotification, + >, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(16, value.prepare(builder).downcast()) + } + + pub fn create_dominant_speaker_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset< + super::active_speaker_observer::DominantSpeakerNotification, + >, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(17, value.prepare(builder).downcast()) + } + + pub fn create_volumes_notification( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset< + super::audio_level_observer::VolumesNotification, + >, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(18, value.prepare(builder).downcast()) + } + } + + impl ::planus::WriteAsUnion for Body { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::UnionOffset { + match self { + Self::SendRtcpNotification(value) => { + Self::create_send_rtcp_notification(builder, value) + } + Self::SctpStateChangeNotification(value) => { + Self::create_sctp_state_change_notification(builder, value) + } + Self::SendNotification(value) => { + Self::create_send_notification(builder, value) + } + Self::TraceNotification(value) => { + Self::create_trace_notification(builder, value) + } + Self::IceSelectedTupleChangeNotification(value) => { + Self::create_ice_selected_tuple_change_notification(builder, value) + } + Self::IceStateChangeNotification(value) => { + Self::create_ice_state_change_notification(builder, value) + } + Self::DtlsStateChangeNotification(value) => { + Self::create_dtls_state_change_notification(builder, value) + } + Self::TupleNotification(value) => { + Self::create_tuple_notification(builder, value) + } + Self::RtcpTupleNotification(value) => { + Self::create_rtcp_tuple_notification(builder, value) + } + Self::RtcpNotification(value) => { + Self::create_rtcp_notification(builder, value) + } + Self::ScoreNotification(value) => { + Self::create_score_notification(builder, value) + } + Self::VideoOrientationChangeNotification(value) => { + Self::create_video_orientation_change_notification(builder, value) + } + Self::LayersChangeNotification(value) => { + Self::create_layers_change_notification(builder, value) + } + Self::RtpNotification(value) => { + Self::create_rtp_notification(builder, value) + } + Self::MessageNotification(value) => { + Self::create_message_notification(builder, value) + } + Self::BufferedAmountLowNotification(value) => { + Self::create_buffered_amount_low_notification(builder, value) + } + Self::DominantSpeakerNotification(value) => { + Self::create_dominant_speaker_notification(builder, value) + } + Self::VolumesNotification(value) => { + Self::create_volumes_notification(builder, value) + } + } + } + } + + impl ::planus::WriteAsOptionalUnion for Body { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::UnionOffset> { + ::core::option::Option::Some(::planus::WriteAsUnion::prepare(self, builder)) + } + } + + #[derive(Copy, Clone, Debug)] + pub enum BodyRef<'a> { + SendRtcpNotification(super::transport::SendRtcpNotificationRef<'a>), + SctpStateChangeNotification(super::transport::SctpStateChangeNotificationRef<'a>), + SendNotification(super::data_producer::SendNotificationRef<'a>), + TraceNotification(super::consumer::TraceNotificationRef<'a>), + IceSelectedTupleChangeNotification( + super::web_rtc_transport::IceSelectedTupleChangeNotificationRef<'a>, + ), + IceStateChangeNotification( + super::web_rtc_transport::IceStateChangeNotificationRef<'a>, + ), + DtlsStateChangeNotification( + super::web_rtc_transport::DtlsStateChangeNotificationRef<'a>, + ), + TupleNotification(super::plain_transport::TupleNotificationRef<'a>), + RtcpTupleNotification(super::plain_transport::RtcpTupleNotificationRef<'a>), + RtcpNotification(super::direct_transport::RtcpNotificationRef<'a>), + ScoreNotification(super::consumer::ScoreNotificationRef<'a>), + VideoOrientationChangeNotification( + super::producer::VideoOrientationChangeNotificationRef<'a>, + ), + LayersChangeNotification(super::consumer::LayersChangeNotificationRef<'a>), + RtpNotification(super::consumer::RtpNotificationRef<'a>), + MessageNotification(super::data_consumer::MessageNotificationRef<'a>), + BufferedAmountLowNotification( + super::data_consumer::BufferedAmountLowNotificationRef<'a>, + ), + DominantSpeakerNotification( + super::active_speaker_observer::DominantSpeakerNotificationRef<'a>, + ), + VolumesNotification(super::audio_level_observer::VolumesNotificationRef<'a>), + } + + impl<'a> ::core::convert::TryFrom> for Body { + type Error = ::planus::Error; + + fn try_from(value: BodyRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(match value { + BodyRef::SendRtcpNotification(value) => { + Body::SendRtcpNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::SctpStateChangeNotification(value) => { + Body::SctpStateChangeNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::SendNotification(value) => { + Body::SendNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::TraceNotification(value) => { + Body::TraceNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::IceSelectedTupleChangeNotification(value) => { + Body::IceSelectedTupleChangeNotification( + ::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + ), + ) + } + + BodyRef::IceStateChangeNotification(value) => { + Body::IceStateChangeNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::DtlsStateChangeNotification(value) => { + Body::DtlsStateChangeNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::TupleNotification(value) => { + Body::TupleNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::RtcpTupleNotification(value) => { + Body::RtcpTupleNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::RtcpNotification(value) => { + Body::RtcpNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::ScoreNotification(value) => { + Body::ScoreNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::VideoOrientationChangeNotification(value) => { + Body::VideoOrientationChangeNotification( + ::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + ), + ) + } + + BodyRef::LayersChangeNotification(value) => { + Body::LayersChangeNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::RtpNotification(value) => { + Body::RtpNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::MessageNotification(value) => { + Body::MessageNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::BufferedAmountLowNotification(value) => { + Body::BufferedAmountLowNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::DominantSpeakerNotification(value) => { + Body::DominantSpeakerNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::VolumesNotification(value) => { + Body::VolumesNotification(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + }) + } + } + + impl<'a> ::planus::TableReadUnion<'a> for BodyRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + field_offset: usize, + tag: u8, + ) -> ::core::result::Result { + match tag { + 1 => ::core::result::Result::Ok(Self::SendRtcpNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 2 => ::core::result::Result::Ok(Self::SctpStateChangeNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 3 => ::core::result::Result::Ok(Self::SendNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 4 => ::core::result::Result::Ok(Self::TraceNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 5 => ::core::result::Result::Ok(Self::IceSelectedTupleChangeNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 6 => ::core::result::Result::Ok(Self::IceStateChangeNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 7 => ::core::result::Result::Ok(Self::DtlsStateChangeNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 8 => ::core::result::Result::Ok(Self::TupleNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 9 => ::core::result::Result::Ok(Self::RtcpTupleNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 10 => ::core::result::Result::Ok(Self::RtcpNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 11 => ::core::result::Result::Ok(Self::ScoreNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 12 => ::core::result::Result::Ok(Self::VideoOrientationChangeNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 13 => ::core::result::Result::Ok(Self::LayersChangeNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 14 => ::core::result::Result::Ok(Self::RtpNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 15 => ::core::result::Result::Ok(Self::MessageNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 16 => ::core::result::Result::Ok(Self::BufferedAmountLowNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 17 => ::core::result::Result::Ok(Self::DominantSpeakerNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 18 => ::core::result::Result::Ok(Self::VolumesNotification( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + _ => ::core::result::Result::Err( + ::planus::errors::ErrorKind::UnknownUnionTag { tag }, + ), + } + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Notification { + pub handler_id: ::core::option::Option<::planus::alloc::string::String>, + pub event: self::Event, + pub body: ::core::option::Option, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for Notification { + fn default() -> Self { + Self { + handler_id: ::core::default::Default::default(), + event: self::Event::TransportSendRtcp, + body: ::core::default::Default::default(), + } + } + } + + impl Notification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_handler_id: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + field_event: impl ::planus::WriteAsDefault, + field_body: impl ::planus::WriteAsOptionalUnion, + ) -> ::planus::Offset { + let prepared_handler_id = field_handler_id.prepare(builder); + + let prepared_event = + field_event.prepare(builder, &self::Event::TransportSendRtcp); + + let prepared_body = field_body.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<8, 10>::new(builder); + + if prepared_handler_id.is_some() { + table_writer.calculate_size::<::planus::Offset>(2); + } + if prepared_event.is_some() { + table_writer.calculate_size::(4); + } + if prepared_body.is_some() { + table_writer.calculate_size::(6); + table_writer.calculate_size::<::planus::Offset>(8); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_handler_id) = + prepared_handler_id + { + table_writer.write::<_, _, 4>(0, &prepared_handler_id); + } + if let ::core::option::Option::Some(prepared_body) = prepared_body { + table_writer.write::<_, _, 4>(3, &prepared_body.offset()); + } + if let ::core::option::Option::Some(prepared_event) = prepared_event { + table_writer.write::<_, _, 1>(1, &prepared_event); + } + if let ::core::option::Option::Some(prepared_body) = prepared_body { + table_writer.write::<_, _, 1>(2, &prepared_body.tag()); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Notification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Notification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Notification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + Notification::create(builder, &self.handler_id, &self.event, &self.body) + } + } + + #[derive(Copy, Clone)] + pub struct NotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> NotificationRef<'a> { + pub fn handler_id( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(0, "Notification", "handler_id") + } + + pub fn event(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "Notification", "event")? + .unwrap_or(self::Event::TransportSendRtcp), + ) + } + + pub fn body(&self) -> ::planus::Result<::core::option::Option>> { + self.0.access_union(2, "Notification", "body") + } + } + + impl<'a> ::core::fmt::Debug for NotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("NotificationRef"); + if let ::core::option::Option::Some(field_handler_id) = + self.handler_id().transpose() + { + f.field("handler_id", &field_handler_id); + } + f.field("event", &self.event()); + if let ::core::option::Option::Some(field_body) = self.body().transpose() { + f.field("body", &field_body); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Notification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: NotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + handler_id: if let ::core::option::Option::Some(handler_id) = + value.handler_id()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + handler_id, + )?) + } else { + ::core::option::Option::None + }, + event: ::core::convert::TryInto::try_into(value.event()?)?, + body: if let ::core::option::Option::Some(body) = value.body()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(body)?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for NotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for NotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[NotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Notification { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for NotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[NotificationRef]", "read_as_root", 0) + }) + } + } + } + pub mod request { + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum Method { + WorkerClose = 0, + WorkerDump = 1, + WorkerGetResourceUsage = 2, + WorkerUpdateSettings = 3, + WorkerCreateWebrtcServer = 4, + WorkerCreateRouter = 5, + WorkerWebrtcServerClose = 6, + WorkerCloseRouter = 7, + WebrtcServerDump = 8, + RouterDump = 9, + RouterCreateWebrtcTransport = 10, + RouterCreateWebrtcTransportWithServer = 11, + RouterCreatePlainTransport = 12, + RouterCreatePipeTransport = 13, + RouterCreateDirectTransport = 14, + RouterCloseTransport = 15, + RouterCreateActiveSpeakerObserver = 16, + RouterCreateAudioLevelObserver = 17, + RouterCloseRtpObserver = 18, + TransportDump = 19, + TransportGetStats = 20, + TransportConnect = 21, + TransportSetMaxIncomingBitrate = 22, + TransportSetMaxOutgoingBitrate = 23, + TransportSetMinOutgoingBitrate = 24, + TransportRestartIce = 25, + TransportProduce = 26, + TransportProduceData = 27, + TransportConsume = 28, + TransportConsumeData = 29, + TransportEnableTraceEvent = 30, + TransportCloseProducer = 31, + TransportCloseConsumer = 32, + TransportCloseDataProducer = 33, + TransportCloseDataConsumer = 34, + PlainTransportConnect = 35, + PipeTransportConnect = 36, + WebrtcTransportConnect = 37, + ProducerDump = 38, + ProducerGetStats = 39, + ProducerPause = 40, + ProducerResume = 41, + ProducerEnableTraceEvent = 42, + ConsumerDump = 43, + ConsumerGetStats = 44, + ConsumerPause = 45, + ConsumerResume = 46, + ConsumerSetPreferredLayers = 47, + ConsumerSetPriority = 48, + ConsumerRequestKeyFrame = 49, + ConsumerEnableTraceEvent = 50, + DataProducerDump = 51, + DataProducerGetStats = 52, + DataConsumerDump = 53, + DataConsumerGetStats = 54, + DataConsumerGetBufferedAmount = 55, + DataConsumerSetBufferedAmountLowThreshold = 56, + DataConsumerSend = 57, + RtpObserverPause = 58, + RtpObserverResume = 59, + RtpObserverAddProducer = 60, + RtpObserverRemoveProducer = 61, + } + + impl ::core::convert::TryFrom for Method { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 0 => ::core::result::Result::Ok(Method::WorkerClose), + 1 => ::core::result::Result::Ok(Method::WorkerDump), + 2 => ::core::result::Result::Ok(Method::WorkerGetResourceUsage), + 3 => ::core::result::Result::Ok(Method::WorkerUpdateSettings), + 4 => ::core::result::Result::Ok(Method::WorkerCreateWebrtcServer), + 5 => ::core::result::Result::Ok(Method::WorkerCreateRouter), + 6 => ::core::result::Result::Ok(Method::WorkerWebrtcServerClose), + 7 => ::core::result::Result::Ok(Method::WorkerCloseRouter), + 8 => ::core::result::Result::Ok(Method::WebrtcServerDump), + 9 => ::core::result::Result::Ok(Method::RouterDump), + 10 => ::core::result::Result::Ok(Method::RouterCreateWebrtcTransport), + 11 => ::core::result::Result::Ok( + Method::RouterCreateWebrtcTransportWithServer, + ), + 12 => ::core::result::Result::Ok(Method::RouterCreatePlainTransport), + 13 => ::core::result::Result::Ok(Method::RouterCreatePipeTransport), + 14 => ::core::result::Result::Ok(Method::RouterCreateDirectTransport), + 15 => ::core::result::Result::Ok(Method::RouterCloseTransport), + 16 => ::core::result::Result::Ok(Method::RouterCreateActiveSpeakerObserver), + 17 => ::core::result::Result::Ok(Method::RouterCreateAudioLevelObserver), + 18 => ::core::result::Result::Ok(Method::RouterCloseRtpObserver), + 19 => ::core::result::Result::Ok(Method::TransportDump), + 20 => ::core::result::Result::Ok(Method::TransportGetStats), + 21 => ::core::result::Result::Ok(Method::TransportConnect), + 22 => ::core::result::Result::Ok(Method::TransportSetMaxIncomingBitrate), + 23 => ::core::result::Result::Ok(Method::TransportSetMaxOutgoingBitrate), + 24 => ::core::result::Result::Ok(Method::TransportSetMinOutgoingBitrate), + 25 => ::core::result::Result::Ok(Method::TransportRestartIce), + 26 => ::core::result::Result::Ok(Method::TransportProduce), + 27 => ::core::result::Result::Ok(Method::TransportProduceData), + 28 => ::core::result::Result::Ok(Method::TransportConsume), + 29 => ::core::result::Result::Ok(Method::TransportConsumeData), + 30 => ::core::result::Result::Ok(Method::TransportEnableTraceEvent), + 31 => ::core::result::Result::Ok(Method::TransportCloseProducer), + 32 => ::core::result::Result::Ok(Method::TransportCloseConsumer), + 33 => ::core::result::Result::Ok(Method::TransportCloseDataProducer), + 34 => ::core::result::Result::Ok(Method::TransportCloseDataConsumer), + 35 => ::core::result::Result::Ok(Method::PlainTransportConnect), + 36 => ::core::result::Result::Ok(Method::PipeTransportConnect), + 37 => ::core::result::Result::Ok(Method::WebrtcTransportConnect), + 38 => ::core::result::Result::Ok(Method::ProducerDump), + 39 => ::core::result::Result::Ok(Method::ProducerGetStats), + 40 => ::core::result::Result::Ok(Method::ProducerPause), + 41 => ::core::result::Result::Ok(Method::ProducerResume), + 42 => ::core::result::Result::Ok(Method::ProducerEnableTraceEvent), + 43 => ::core::result::Result::Ok(Method::ConsumerDump), + 44 => ::core::result::Result::Ok(Method::ConsumerGetStats), + 45 => ::core::result::Result::Ok(Method::ConsumerPause), + 46 => ::core::result::Result::Ok(Method::ConsumerResume), + 47 => ::core::result::Result::Ok(Method::ConsumerSetPreferredLayers), + 48 => ::core::result::Result::Ok(Method::ConsumerSetPriority), + 49 => ::core::result::Result::Ok(Method::ConsumerRequestKeyFrame), + 50 => ::core::result::Result::Ok(Method::ConsumerEnableTraceEvent), + 51 => ::core::result::Result::Ok(Method::DataProducerDump), + 52 => ::core::result::Result::Ok(Method::DataProducerGetStats), + 53 => ::core::result::Result::Ok(Method::DataConsumerDump), + 54 => ::core::result::Result::Ok(Method::DataConsumerGetStats), + 55 => ::core::result::Result::Ok(Method::DataConsumerGetBufferedAmount), + 56 => ::core::result::Result::Ok( + Method::DataConsumerSetBufferedAmountLowThreshold, + ), + 57 => ::core::result::Result::Ok(Method::DataConsumerSend), + 58 => ::core::result::Result::Ok(Method::RtpObserverPause), + 59 => ::core::result::Result::Ok(Method::RtpObserverResume), + 60 => ::core::result::Result::Ok(Method::RtpObserverAddProducer), + 61 => ::core::result::Result::Ok(Method::RtpObserverRemoveProducer), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: Method) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for Method { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for Method { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for Method { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> Method { + *self + } + } + + impl ::planus::WriteAsDefault for Method { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &Method, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for Method { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for Method { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for Method { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "Method", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for Method { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub enum Body { + UpdateSettingsRequest( + ::planus::alloc::boxed::Box, + ), + CreateWebRtcServerRequest( + ::planus::alloc::boxed::Box, + ), + CloseWebRtcServerRequest( + ::planus::alloc::boxed::Box, + ), + CreateRouterRequest( + ::planus::alloc::boxed::Box, + ), + CloseRouterRequest(::planus::alloc::boxed::Box), + CreateWebRtcTransportRequest( + ::planus::alloc::boxed::Box, + ), + CreatePlainTransportRequest( + ::planus::alloc::boxed::Box, + ), + CreatePipeTransportRequest( + ::planus::alloc::boxed::Box, + ), + CreateDirectTransportRequest( + ::planus::alloc::boxed::Box, + ), + CreateActiveSpeakerObserverRequest( + ::planus::alloc::boxed::Box, + ), + CreateAudioLevelObserverRequest( + ::planus::alloc::boxed::Box, + ), + CloseTransportRequest( + ::planus::alloc::boxed::Box, + ), + CloseRtpObserverRequest( + ::planus::alloc::boxed::Box, + ), + SetMaxIncomingBitrateRequest( + ::planus::alloc::boxed::Box, + ), + SetMaxOutgoingBitrateRequest( + ::planus::alloc::boxed::Box, + ), + SetMinOutgoingBitrateRequest( + ::planus::alloc::boxed::Box, + ), + ProduceRequest(::planus::alloc::boxed::Box), + ConsumeRequest(::planus::alloc::boxed::Box), + ProduceDataRequest( + ::planus::alloc::boxed::Box, + ), + ConsumeDataRequest( + ::planus::alloc::boxed::Box, + ), + EnableTraceEventRequest( + ::planus::alloc::boxed::Box, + ), + CloseProducerRequest( + ::planus::alloc::boxed::Box, + ), + CloseConsumerRequest( + ::planus::alloc::boxed::Box, + ), + CloseDataProducerRequest( + ::planus::alloc::boxed::Box, + ), + CloseDataConsumerRequest( + ::planus::alloc::boxed::Box, + ), + ConnectRequest( + ::planus::alloc::boxed::Box, + ), + SetPreferredLayersRequest( + ::planus::alloc::boxed::Box, + ), + SetPriorityRequest( + ::planus::alloc::boxed::Box, + ), + SetBufferedAmountLowThresholdRequest( + ::planus::alloc::boxed::Box< + super::data_consumer::SetBufferedAmountLowThresholdRequest, + >, + ), + SendRequest(::planus::alloc::boxed::Box), + AddProducerRequest( + ::planus::alloc::boxed::Box, + ), + RemoveProducerRequest( + ::planus::alloc::boxed::Box, + ), + } + + impl Body { + pub fn create_update_settings_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(1, value.prepare(builder).downcast()) + } + + pub fn create_create_web_rtc_server_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(2, value.prepare(builder).downcast()) + } + + pub fn create_close_web_rtc_server_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(3, value.prepare(builder).downcast()) + } + + pub fn create_create_router_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(4, value.prepare(builder).downcast()) + } + + pub fn create_close_router_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(5, value.prepare(builder).downcast()) + } + + pub fn create_create_web_rtc_transport_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(6, value.prepare(builder).downcast()) + } + + pub fn create_create_plain_transport_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(7, value.prepare(builder).downcast()) + } + + pub fn create_create_pipe_transport_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(8, value.prepare(builder).downcast()) + } + + pub fn create_create_direct_transport_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(9, value.prepare(builder).downcast()) + } + + pub fn create_create_active_speaker_observer_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset< + super::router::CreateActiveSpeakerObserverRequest, + >, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(10, value.prepare(builder).downcast()) + } + + pub fn create_create_audio_level_observer_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(11, value.prepare(builder).downcast()) + } + + pub fn create_close_transport_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(12, value.prepare(builder).downcast()) + } + + pub fn create_close_rtp_observer_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(13, value.prepare(builder).downcast()) + } + + pub fn create_set_max_incoming_bitrate_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(14, value.prepare(builder).downcast()) + } + + pub fn create_set_max_outgoing_bitrate_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(15, value.prepare(builder).downcast()) + } + + pub fn create_set_min_outgoing_bitrate_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(16, value.prepare(builder).downcast()) + } + + pub fn create_produce_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(17, value.prepare(builder).downcast()) + } + + pub fn create_consume_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(18, value.prepare(builder).downcast()) + } + + pub fn create_produce_data_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(19, value.prepare(builder).downcast()) + } + + pub fn create_consume_data_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(20, value.prepare(builder).downcast()) + } + + pub fn create_enable_trace_event_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(21, value.prepare(builder).downcast()) + } + + pub fn create_close_producer_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(22, value.prepare(builder).downcast()) + } + + pub fn create_close_consumer_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(23, value.prepare(builder).downcast()) + } + + pub fn create_close_data_producer_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(24, value.prepare(builder).downcast()) + } + + pub fn create_close_data_consumer_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(25, value.prepare(builder).downcast()) + } + + pub fn create_connect_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(26, value.prepare(builder).downcast()) + } + + pub fn create_set_preferred_layers_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(27, value.prepare(builder).downcast()) + } + + pub fn create_set_priority_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(28, value.prepare(builder).downcast()) + } + + pub fn create_set_buffered_amount_low_threshold_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset< + super::data_consumer::SetBufferedAmountLowThresholdRequest, + >, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(29, value.prepare(builder).downcast()) + } + + pub fn create_send_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(30, value.prepare(builder).downcast()) + } + + pub fn create_add_producer_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(31, value.prepare(builder).downcast()) + } + + pub fn create_remove_producer_request( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(32, value.prepare(builder).downcast()) + } + } + + impl ::planus::WriteAsUnion for Body { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::UnionOffset { + match self { + Self::UpdateSettingsRequest(value) => { + Self::create_update_settings_request(builder, value) + } + Self::CreateWebRtcServerRequest(value) => { + Self::create_create_web_rtc_server_request(builder, value) + } + Self::CloseWebRtcServerRequest(value) => { + Self::create_close_web_rtc_server_request(builder, value) + } + Self::CreateRouterRequest(value) => { + Self::create_create_router_request(builder, value) + } + Self::CloseRouterRequest(value) => { + Self::create_close_router_request(builder, value) + } + Self::CreateWebRtcTransportRequest(value) => { + Self::create_create_web_rtc_transport_request(builder, value) + } + Self::CreatePlainTransportRequest(value) => { + Self::create_create_plain_transport_request(builder, value) + } + Self::CreatePipeTransportRequest(value) => { + Self::create_create_pipe_transport_request(builder, value) + } + Self::CreateDirectTransportRequest(value) => { + Self::create_create_direct_transport_request(builder, value) + } + Self::CreateActiveSpeakerObserverRequest(value) => { + Self::create_create_active_speaker_observer_request(builder, value) + } + Self::CreateAudioLevelObserverRequest(value) => { + Self::create_create_audio_level_observer_request(builder, value) + } + Self::CloseTransportRequest(value) => { + Self::create_close_transport_request(builder, value) + } + Self::CloseRtpObserverRequest(value) => { + Self::create_close_rtp_observer_request(builder, value) + } + Self::SetMaxIncomingBitrateRequest(value) => { + Self::create_set_max_incoming_bitrate_request(builder, value) + } + Self::SetMaxOutgoingBitrateRequest(value) => { + Self::create_set_max_outgoing_bitrate_request(builder, value) + } + Self::SetMinOutgoingBitrateRequest(value) => { + Self::create_set_min_outgoing_bitrate_request(builder, value) + } + Self::ProduceRequest(value) => Self::create_produce_request(builder, value), + Self::ConsumeRequest(value) => Self::create_consume_request(builder, value), + Self::ProduceDataRequest(value) => { + Self::create_produce_data_request(builder, value) + } + Self::ConsumeDataRequest(value) => { + Self::create_consume_data_request(builder, value) + } + Self::EnableTraceEventRequest(value) => { + Self::create_enable_trace_event_request(builder, value) + } + Self::CloseProducerRequest(value) => { + Self::create_close_producer_request(builder, value) + } + Self::CloseConsumerRequest(value) => { + Self::create_close_consumer_request(builder, value) + } + Self::CloseDataProducerRequest(value) => { + Self::create_close_data_producer_request(builder, value) + } + Self::CloseDataConsumerRequest(value) => { + Self::create_close_data_consumer_request(builder, value) + } + Self::ConnectRequest(value) => Self::create_connect_request(builder, value), + Self::SetPreferredLayersRequest(value) => { + Self::create_set_preferred_layers_request(builder, value) + } + Self::SetPriorityRequest(value) => { + Self::create_set_priority_request(builder, value) + } + Self::SetBufferedAmountLowThresholdRequest(value) => { + Self::create_set_buffered_amount_low_threshold_request(builder, value) + } + Self::SendRequest(value) => Self::create_send_request(builder, value), + Self::AddProducerRequest(value) => { + Self::create_add_producer_request(builder, value) + } + Self::RemoveProducerRequest(value) => { + Self::create_remove_producer_request(builder, value) + } + } + } + } + + impl ::planus::WriteAsOptionalUnion for Body { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::UnionOffset> { + ::core::option::Option::Some(::planus::WriteAsUnion::prepare(self, builder)) + } + } + + #[derive(Copy, Clone, Debug)] + pub enum BodyRef<'a> { + UpdateSettingsRequest(super::worker::UpdateSettingsRequestRef<'a>), + CreateWebRtcServerRequest(super::worker::CreateWebRtcServerRequestRef<'a>), + CloseWebRtcServerRequest(super::worker::CloseWebRtcServerRequestRef<'a>), + CreateRouterRequest(super::worker::CreateRouterRequestRef<'a>), + CloseRouterRequest(super::worker::CloseRouterRequestRef<'a>), + CreateWebRtcTransportRequest(super::router::CreateWebRtcTransportRequestRef<'a>), + CreatePlainTransportRequest(super::router::CreatePlainTransportRequestRef<'a>), + CreatePipeTransportRequest(super::router::CreatePipeTransportRequestRef<'a>), + CreateDirectTransportRequest(super::router::CreateDirectTransportRequestRef<'a>), + CreateActiveSpeakerObserverRequest( + super::router::CreateActiveSpeakerObserverRequestRef<'a>, + ), + CreateAudioLevelObserverRequest( + super::router::CreateAudioLevelObserverRequestRef<'a>, + ), + CloseTransportRequest(super::router::CloseTransportRequestRef<'a>), + CloseRtpObserverRequest(super::router::CloseRtpObserverRequestRef<'a>), + SetMaxIncomingBitrateRequest(super::transport::SetMaxIncomingBitrateRequestRef<'a>), + SetMaxOutgoingBitrateRequest(super::transport::SetMaxOutgoingBitrateRequestRef<'a>), + SetMinOutgoingBitrateRequest(super::transport::SetMinOutgoingBitrateRequestRef<'a>), + ProduceRequest(super::transport::ProduceRequestRef<'a>), + ConsumeRequest(super::transport::ConsumeRequestRef<'a>), + ProduceDataRequest(super::transport::ProduceDataRequestRef<'a>), + ConsumeDataRequest(super::transport::ConsumeDataRequestRef<'a>), + EnableTraceEventRequest(super::consumer::EnableTraceEventRequestRef<'a>), + CloseProducerRequest(super::transport::CloseProducerRequestRef<'a>), + CloseConsumerRequest(super::transport::CloseConsumerRequestRef<'a>), + CloseDataProducerRequest(super::transport::CloseDataProducerRequestRef<'a>), + CloseDataConsumerRequest(super::transport::CloseDataConsumerRequestRef<'a>), + ConnectRequest(super::web_rtc_transport::ConnectRequestRef<'a>), + SetPreferredLayersRequest(super::consumer::SetPreferredLayersRequestRef<'a>), + SetPriorityRequest(super::consumer::SetPriorityRequestRef<'a>), + SetBufferedAmountLowThresholdRequest( + super::data_consumer::SetBufferedAmountLowThresholdRequestRef<'a>, + ), + SendRequest(super::data_consumer::SendRequestRef<'a>), + AddProducerRequest(super::rtp_observer::AddProducerRequestRef<'a>), + RemoveProducerRequest(super::rtp_observer::RemoveProducerRequestRef<'a>), + } + + impl<'a> ::core::convert::TryFrom> for Body { + type Error = ::planus::Error; + + fn try_from(value: BodyRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(match value { + BodyRef::UpdateSettingsRequest(value) => { + Body::UpdateSettingsRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::CreateWebRtcServerRequest(value) => { + Body::CreateWebRtcServerRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::CloseWebRtcServerRequest(value) => { + Body::CloseWebRtcServerRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::CreateRouterRequest(value) => { + Body::CreateRouterRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::CloseRouterRequest(value) => { + Body::CloseRouterRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::CreateWebRtcTransportRequest(value) => { + Body::CreateWebRtcTransportRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::CreatePlainTransportRequest(value) => { + Body::CreatePlainTransportRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::CreatePipeTransportRequest(value) => { + Body::CreatePipeTransportRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::CreateDirectTransportRequest(value) => { + Body::CreateDirectTransportRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::CreateActiveSpeakerObserverRequest(value) => { + Body::CreateActiveSpeakerObserverRequest( + ::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + ), + ) + } + + BodyRef::CreateAudioLevelObserverRequest(value) => { + Body::CreateAudioLevelObserverRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::CloseTransportRequest(value) => { + Body::CloseTransportRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::CloseRtpObserverRequest(value) => { + Body::CloseRtpObserverRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::SetMaxIncomingBitrateRequest(value) => { + Body::SetMaxIncomingBitrateRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::SetMaxOutgoingBitrateRequest(value) => { + Body::SetMaxOutgoingBitrateRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::SetMinOutgoingBitrateRequest(value) => { + Body::SetMinOutgoingBitrateRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::ProduceRequest(value) => { + Body::ProduceRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::ConsumeRequest(value) => { + Body::ConsumeRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::ProduceDataRequest(value) => { + Body::ProduceDataRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::ConsumeDataRequest(value) => { + Body::ConsumeDataRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::EnableTraceEventRequest(value) => { + Body::EnableTraceEventRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::CloseProducerRequest(value) => { + Body::CloseProducerRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::CloseConsumerRequest(value) => { + Body::CloseConsumerRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::CloseDataProducerRequest(value) => { + Body::CloseDataProducerRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::CloseDataConsumerRequest(value) => { + Body::CloseDataConsumerRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::ConnectRequest(value) => { + Body::ConnectRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::SetPreferredLayersRequest(value) => { + Body::SetPreferredLayersRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::SetPriorityRequest(value) => { + Body::SetPriorityRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::SetBufferedAmountLowThresholdRequest(value) => { + Body::SetBufferedAmountLowThresholdRequest( + ::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + ), + ) + } + + BodyRef::SendRequest(value) => { + Body::SendRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::AddProducerRequest(value) => { + Body::AddProducerRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::RemoveProducerRequest(value) => { + Body::RemoveProducerRequest(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + }) + } + } + + impl<'a> ::planus::TableReadUnion<'a> for BodyRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + field_offset: usize, + tag: u8, + ) -> ::core::result::Result { + match tag { + 1 => ::core::result::Result::Ok(Self::UpdateSettingsRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 2 => ::core::result::Result::Ok(Self::CreateWebRtcServerRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 3 => ::core::result::Result::Ok(Self::CloseWebRtcServerRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 4 => ::core::result::Result::Ok(Self::CreateRouterRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 5 => ::core::result::Result::Ok(Self::CloseRouterRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 6 => ::core::result::Result::Ok(Self::CreateWebRtcTransportRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 7 => ::core::result::Result::Ok(Self::CreatePlainTransportRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 8 => ::core::result::Result::Ok(Self::CreatePipeTransportRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 9 => ::core::result::Result::Ok(Self::CreateDirectTransportRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 10 => ::core::result::Result::Ok(Self::CreateActiveSpeakerObserverRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 11 => ::core::result::Result::Ok(Self::CreateAudioLevelObserverRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 12 => ::core::result::Result::Ok(Self::CloseTransportRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 13 => ::core::result::Result::Ok(Self::CloseRtpObserverRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 14 => ::core::result::Result::Ok(Self::SetMaxIncomingBitrateRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 15 => ::core::result::Result::Ok(Self::SetMaxOutgoingBitrateRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 16 => ::core::result::Result::Ok(Self::SetMinOutgoingBitrateRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 17 => ::core::result::Result::Ok(Self::ProduceRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 18 => ::core::result::Result::Ok(Self::ConsumeRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 19 => ::core::result::Result::Ok(Self::ProduceDataRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 20 => ::core::result::Result::Ok(Self::ConsumeDataRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 21 => ::core::result::Result::Ok(Self::EnableTraceEventRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 22 => ::core::result::Result::Ok(Self::CloseProducerRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 23 => ::core::result::Result::Ok(Self::CloseConsumerRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 24 => ::core::result::Result::Ok(Self::CloseDataProducerRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 25 => ::core::result::Result::Ok(Self::CloseDataConsumerRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 26 => ::core::result::Result::Ok(Self::ConnectRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 27 => ::core::result::Result::Ok(Self::SetPreferredLayersRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 28 => ::core::result::Result::Ok(Self::SetPriorityRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 29 => { + ::core::result::Result::Ok(Self::SetBufferedAmountLowThresholdRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )) + } + 30 => ::core::result::Result::Ok(Self::SendRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 31 => ::core::result::Result::Ok(Self::AddProducerRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 32 => ::core::result::Result::Ok(Self::RemoveProducerRequest( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + _ => ::core::result::Result::Err( + ::planus::errors::ErrorKind::UnknownUnionTag { tag }, + ), + } + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct Request { + pub id: u32, + pub method: self::Method, + pub handler_id: ::core::option::Option<::planus::alloc::string::String>, + pub body: ::core::option::Option, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for Request { + fn default() -> Self { + Self { + id: 0, + method: self::Method::WorkerClose, + handler_id: ::core::default::Default::default(), + body: ::core::default::Default::default(), + } + } + } + + impl Request { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_id: impl ::planus::WriteAsDefault, + field_method: impl ::planus::WriteAsDefault, + field_handler_id: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + field_body: impl ::planus::WriteAsOptionalUnion, + ) -> ::planus::Offset { + let prepared_id = field_id.prepare(builder, &0); + + let prepared_method = field_method.prepare(builder, &self::Method::WorkerClose); + + let prepared_handler_id = field_handler_id.prepare(builder); + + let prepared_body = field_body.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<10, 14>::new(builder); + + if prepared_id.is_some() { + table_writer.calculate_size::(2); + } + if prepared_method.is_some() { + table_writer.calculate_size::(4); + } + if prepared_handler_id.is_some() { + table_writer.calculate_size::<::planus::Offset>(6); + } + if prepared_body.is_some() { + table_writer.calculate_size::(8); + table_writer.calculate_size::<::planus::Offset>(10); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_id) = prepared_id { + table_writer.write::<_, _, 4>(0, &prepared_id); + } + if let ::core::option::Option::Some(prepared_handler_id) = + prepared_handler_id + { + table_writer.write::<_, _, 4>(2, &prepared_handler_id); + } + if let ::core::option::Option::Some(prepared_body) = prepared_body { + table_writer.write::<_, _, 4>(4, &prepared_body.offset()); + } + if let ::core::option::Option::Some(prepared_method) = prepared_method { + table_writer.write::<_, _, 1>(1, &prepared_method); + } + if let ::core::option::Option::Some(prepared_body) = prepared_body { + table_writer.write::<_, _, 1>(3, &prepared_body.tag()); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Request { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Request { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Request { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Request::create( + builder, + &self.id, + &self.method, + &self.handler_id, + &self.body, + ) + } + } + + #[derive(Copy, Clone)] + pub struct RequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RequestRef<'a> { + pub fn id(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(0, "Request", "id")?.unwrap_or(0)) + } + + pub fn method(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "Request", "method")? + .unwrap_or(self::Method::WorkerClose), + ) + } + + pub fn handler_id( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(2, "Request", "handler_id") + } + + pub fn body(&self) -> ::planus::Result<::core::option::Option>> { + self.0.access_union(3, "Request", "body") + } + } + + impl<'a> ::core::fmt::Debug for RequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RequestRef"); + f.field("id", &self.id()); + f.field("method", &self.method()); + if let ::core::option::Option::Some(field_handler_id) = + self.handler_id().transpose() + { + f.field("handler_id", &field_handler_id); + } + if let ::core::option::Option::Some(field_body) = self.body().transpose() { + f.field("body", &field_body); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Request { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + id: ::core::convert::TryInto::try_into(value.id()?)?, + method: ::core::convert::TryInto::try_into(value.method()?)?, + handler_id: if let ::core::option::Option::Some(handler_id) = + value.handler_id()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + handler_id, + )?) + } else { + ::core::option::Option::None + }, + body: if let ::core::option::Option::Some(body) = value.body()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(body)?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Request { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[RequestRef]", "read_as_root", 0) + }) + } + } + } + pub mod response { + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub enum Body { + FbsWorkerDumpResponse(::planus::alloc::boxed::Box), + FbsWorkerResourceUsageResponse( + ::planus::alloc::boxed::Box, + ), + FbsWebRtcServerDumpResponse( + ::planus::alloc::boxed::Box, + ), + FbsRouterDumpResponse(::planus::alloc::boxed::Box), + FbsTransportProduceResponse( + ::planus::alloc::boxed::Box, + ), + FbsTransportConsumeResponse( + ::planus::alloc::boxed::Box, + ), + FbsTransportRestartIceResponse( + ::planus::alloc::boxed::Box, + ), + FbsPlainTransportConnectResponse( + ::planus::alloc::boxed::Box, + ), + FbsPlainTransportDumpResponse( + ::planus::alloc::boxed::Box, + ), + FbsPlainTransportGetStatsResponse( + ::planus::alloc::boxed::Box, + ), + FbsPipeTransportConnectResponse( + ::planus::alloc::boxed::Box, + ), + FbsPipeTransportDumpResponse( + ::planus::alloc::boxed::Box, + ), + FbsPipeTransportGetStatsResponse( + ::planus::alloc::boxed::Box, + ), + FbsDirectTransportDumpResponse( + ::planus::alloc::boxed::Box, + ), + FbsDirectTransportGetStatsResponse( + ::planus::alloc::boxed::Box, + ), + FbsWebRtcTransportConnectResponse( + ::planus::alloc::boxed::Box, + ), + FbsWebRtcTransportDumpResponse( + ::planus::alloc::boxed::Box, + ), + FbsWebRtcTransportGetStatsResponse( + ::planus::alloc::boxed::Box, + ), + FbsProducerDumpResponse(::planus::alloc::boxed::Box), + FbsProducerGetStatsResponse( + ::planus::alloc::boxed::Box, + ), + FbsConsumerDumpResponse(::planus::alloc::boxed::Box), + FbsConsumerGetStatsResponse( + ::planus::alloc::boxed::Box, + ), + FbsConsumerSetPreferredLayersResponse( + ::planus::alloc::boxed::Box, + ), + FbsConsumerSetPriorityResponse( + ::planus::alloc::boxed::Box, + ), + FbsDataProducerDumpResponse( + ::planus::alloc::boxed::Box, + ), + FbsDataProducerGetStatsResponse( + ::planus::alloc::boxed::Box, + ), + FbsDataConsumerGetBufferedAmountResponse( + ::planus::alloc::boxed::Box, + ), + FbsDataConsumerDumpResponse( + ::planus::alloc::boxed::Box, + ), + FbsDataConsumerGetStatsResponse( + ::planus::alloc::boxed::Box, + ), + } + + impl Body { + pub fn create_fbs_worker_dump_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(1, value.prepare(builder).downcast()) + } + + pub fn create_fbs_worker_resource_usage_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(2, value.prepare(builder).downcast()) + } + + pub fn create_fbs_web_rtc_server_dump_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(3, value.prepare(builder).downcast()) + } + + pub fn create_fbs_router_dump_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(4, value.prepare(builder).downcast()) + } + + pub fn create_fbs_transport_produce_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(5, value.prepare(builder).downcast()) + } + + pub fn create_fbs_transport_consume_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(6, value.prepare(builder).downcast()) + } + + pub fn create_fbs_transport_restart_ice_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(7, value.prepare(builder).downcast()) + } + + pub fn create_fbs_plain_transport_connect_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(8, value.prepare(builder).downcast()) + } + + pub fn create_fbs_plain_transport_dump_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(9, value.prepare(builder).downcast()) + } + + pub fn create_fbs_plain_transport_get_stats_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(10, value.prepare(builder).downcast()) + } + + pub fn create_fbs_pipe_transport_connect_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(11, value.prepare(builder).downcast()) + } + + pub fn create_fbs_pipe_transport_dump_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(12, value.prepare(builder).downcast()) + } + + pub fn create_fbs_pipe_transport_get_stats_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(13, value.prepare(builder).downcast()) + } + + pub fn create_fbs_direct_transport_dump_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(14, value.prepare(builder).downcast()) + } + + pub fn create_fbs_direct_transport_get_stats_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(15, value.prepare(builder).downcast()) + } + + pub fn create_fbs_web_rtc_transport_connect_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(16, value.prepare(builder).downcast()) + } + + pub fn create_fbs_web_rtc_transport_dump_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(17, value.prepare(builder).downcast()) + } + + pub fn create_fbs_web_rtc_transport_get_stats_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(18, value.prepare(builder).downcast()) + } + + pub fn create_fbs_producer_dump_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(19, value.prepare(builder).downcast()) + } + + pub fn create_fbs_producer_get_stats_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(20, value.prepare(builder).downcast()) + } + + pub fn create_fbs_consumer_dump_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(21, value.prepare(builder).downcast()) + } + + pub fn create_fbs_consumer_get_stats_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(22, value.prepare(builder).downcast()) + } + + pub fn create_fbs_consumer_set_preferred_layers_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(23, value.prepare(builder).downcast()) + } + + pub fn create_fbs_consumer_set_priority_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(24, value.prepare(builder).downcast()) + } + + pub fn create_fbs_data_producer_dump_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(25, value.prepare(builder).downcast()) + } + + pub fn create_fbs_data_producer_get_stats_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(26, value.prepare(builder).downcast()) + } + + pub fn create_fbs_data_consumer_get_buffered_amount_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(27, value.prepare(builder).downcast()) + } + + pub fn create_fbs_data_consumer_dump_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(28, value.prepare(builder).downcast()) + } + + pub fn create_fbs_data_consumer_get_stats_response( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(29, value.prepare(builder).downcast()) + } + } + + impl ::planus::WriteAsUnion for Body { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::UnionOffset { + match self { + Self::FbsWorkerDumpResponse(value) => { + Self::create_fbs_worker_dump_response(builder, value) + } + Self::FbsWorkerResourceUsageResponse(value) => { + Self::create_fbs_worker_resource_usage_response(builder, value) + } + Self::FbsWebRtcServerDumpResponse(value) => { + Self::create_fbs_web_rtc_server_dump_response(builder, value) + } + Self::FbsRouterDumpResponse(value) => { + Self::create_fbs_router_dump_response(builder, value) + } + Self::FbsTransportProduceResponse(value) => { + Self::create_fbs_transport_produce_response(builder, value) + } + Self::FbsTransportConsumeResponse(value) => { + Self::create_fbs_transport_consume_response(builder, value) + } + Self::FbsTransportRestartIceResponse(value) => { + Self::create_fbs_transport_restart_ice_response(builder, value) + } + Self::FbsPlainTransportConnectResponse(value) => { + Self::create_fbs_plain_transport_connect_response(builder, value) + } + Self::FbsPlainTransportDumpResponse(value) => { + Self::create_fbs_plain_transport_dump_response(builder, value) + } + Self::FbsPlainTransportGetStatsResponse(value) => { + Self::create_fbs_plain_transport_get_stats_response(builder, value) + } + Self::FbsPipeTransportConnectResponse(value) => { + Self::create_fbs_pipe_transport_connect_response(builder, value) + } + Self::FbsPipeTransportDumpResponse(value) => { + Self::create_fbs_pipe_transport_dump_response(builder, value) + } + Self::FbsPipeTransportGetStatsResponse(value) => { + Self::create_fbs_pipe_transport_get_stats_response(builder, value) + } + Self::FbsDirectTransportDumpResponse(value) => { + Self::create_fbs_direct_transport_dump_response(builder, value) + } + Self::FbsDirectTransportGetStatsResponse(value) => { + Self::create_fbs_direct_transport_get_stats_response(builder, value) + } + Self::FbsWebRtcTransportConnectResponse(value) => { + Self::create_fbs_web_rtc_transport_connect_response(builder, value) + } + Self::FbsWebRtcTransportDumpResponse(value) => { + Self::create_fbs_web_rtc_transport_dump_response(builder, value) + } + Self::FbsWebRtcTransportGetStatsResponse(value) => { + Self::create_fbs_web_rtc_transport_get_stats_response(builder, value) + } + Self::FbsProducerDumpResponse(value) => { + Self::create_fbs_producer_dump_response(builder, value) + } + Self::FbsProducerGetStatsResponse(value) => { + Self::create_fbs_producer_get_stats_response(builder, value) + } + Self::FbsConsumerDumpResponse(value) => { + Self::create_fbs_consumer_dump_response(builder, value) + } + Self::FbsConsumerGetStatsResponse(value) => { + Self::create_fbs_consumer_get_stats_response(builder, value) + } + Self::FbsConsumerSetPreferredLayersResponse(value) => { + Self::create_fbs_consumer_set_preferred_layers_response(builder, value) + } + Self::FbsConsumerSetPriorityResponse(value) => { + Self::create_fbs_consumer_set_priority_response(builder, value) + } + Self::FbsDataProducerDumpResponse(value) => { + Self::create_fbs_data_producer_dump_response(builder, value) + } + Self::FbsDataProducerGetStatsResponse(value) => { + Self::create_fbs_data_producer_get_stats_response(builder, value) + } + Self::FbsDataConsumerGetBufferedAmountResponse(value) => { + Self::create_fbs_data_consumer_get_buffered_amount_response( + builder, value, + ) + } + Self::FbsDataConsumerDumpResponse(value) => { + Self::create_fbs_data_consumer_dump_response(builder, value) + } + Self::FbsDataConsumerGetStatsResponse(value) => { + Self::create_fbs_data_consumer_get_stats_response(builder, value) + } + } + } + } + + impl ::planus::WriteAsOptionalUnion for Body { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::UnionOffset> { + ::core::option::Option::Some(::planus::WriteAsUnion::prepare(self, builder)) + } + } + + #[derive(Copy, Clone, Debug)] + pub enum BodyRef<'a> { + FbsWorkerDumpResponse(super::worker::DumpResponseRef<'a>), + FbsWorkerResourceUsageResponse(super::worker::ResourceUsageResponseRef<'a>), + FbsWebRtcServerDumpResponse(super::web_rtc_server::DumpResponseRef<'a>), + FbsRouterDumpResponse(super::router::DumpResponseRef<'a>), + FbsTransportProduceResponse(super::transport::ProduceResponseRef<'a>), + FbsTransportConsumeResponse(super::transport::ConsumeResponseRef<'a>), + FbsTransportRestartIceResponse(super::transport::RestartIceResponseRef<'a>), + FbsPlainTransportConnectResponse(super::plain_transport::ConnectResponseRef<'a>), + FbsPlainTransportDumpResponse(super::plain_transport::DumpResponseRef<'a>), + FbsPlainTransportGetStatsResponse(super::plain_transport::GetStatsResponseRef<'a>), + FbsPipeTransportConnectResponse(super::pipe_transport::ConnectResponseRef<'a>), + FbsPipeTransportDumpResponse(super::pipe_transport::DumpResponseRef<'a>), + FbsPipeTransportGetStatsResponse(super::pipe_transport::GetStatsResponseRef<'a>), + FbsDirectTransportDumpResponse(super::direct_transport::DumpResponseRef<'a>), + FbsDirectTransportGetStatsResponse( + super::direct_transport::GetStatsResponseRef<'a>, + ), + FbsWebRtcTransportConnectResponse(super::web_rtc_transport::ConnectResponseRef<'a>), + FbsWebRtcTransportDumpResponse(super::web_rtc_transport::DumpResponseRef<'a>), + FbsWebRtcTransportGetStatsResponse( + super::web_rtc_transport::GetStatsResponseRef<'a>, + ), + FbsProducerDumpResponse(super::producer::DumpResponseRef<'a>), + FbsProducerGetStatsResponse(super::producer::GetStatsResponseRef<'a>), + FbsConsumerDumpResponse(super::consumer::DumpResponseRef<'a>), + FbsConsumerGetStatsResponse(super::consumer::GetStatsResponseRef<'a>), + FbsConsumerSetPreferredLayersResponse( + super::consumer::SetPreferredLayersResponseRef<'a>, + ), + FbsConsumerSetPriorityResponse(super::consumer::SetPriorityResponseRef<'a>), + FbsDataProducerDumpResponse(super::data_producer::DumpResponseRef<'a>), + FbsDataProducerGetStatsResponse(super::data_producer::GetStatsResponseRef<'a>), + FbsDataConsumerGetBufferedAmountResponse( + super::data_consumer::GetBufferedAmountResponseRef<'a>, + ), + FbsDataConsumerDumpResponse(super::data_consumer::DumpResponseRef<'a>), + FbsDataConsumerGetStatsResponse(super::data_consumer::GetStatsResponseRef<'a>), + } + + impl<'a> ::core::convert::TryFrom> for Body { + type Error = ::planus::Error; + + fn try_from(value: BodyRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(match value { + BodyRef::FbsWorkerDumpResponse(value) => { + Body::FbsWorkerDumpResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsWorkerResourceUsageResponse(value) => { + Body::FbsWorkerResourceUsageResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsWebRtcServerDumpResponse(value) => { + Body::FbsWebRtcServerDumpResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsRouterDumpResponse(value) => { + Body::FbsRouterDumpResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsTransportProduceResponse(value) => { + Body::FbsTransportProduceResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsTransportConsumeResponse(value) => { + Body::FbsTransportConsumeResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsTransportRestartIceResponse(value) => { + Body::FbsTransportRestartIceResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsPlainTransportConnectResponse(value) => { + Body::FbsPlainTransportConnectResponse( + ::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + ), + ) + } + + BodyRef::FbsPlainTransportDumpResponse(value) => { + Body::FbsPlainTransportDumpResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsPlainTransportGetStatsResponse(value) => { + Body::FbsPlainTransportGetStatsResponse( + ::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + ), + ) + } + + BodyRef::FbsPipeTransportConnectResponse(value) => { + Body::FbsPipeTransportConnectResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsPipeTransportDumpResponse(value) => { + Body::FbsPipeTransportDumpResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsPipeTransportGetStatsResponse(value) => { + Body::FbsPipeTransportGetStatsResponse( + ::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + ), + ) + } + + BodyRef::FbsDirectTransportDumpResponse(value) => { + Body::FbsDirectTransportDumpResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsDirectTransportGetStatsResponse(value) => { + Body::FbsDirectTransportGetStatsResponse( + ::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + ), + ) + } + + BodyRef::FbsWebRtcTransportConnectResponse(value) => { + Body::FbsWebRtcTransportConnectResponse( + ::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + ), + ) + } + + BodyRef::FbsWebRtcTransportDumpResponse(value) => { + Body::FbsWebRtcTransportDumpResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsWebRtcTransportGetStatsResponse(value) => { + Body::FbsWebRtcTransportGetStatsResponse( + ::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + ), + ) + } + + BodyRef::FbsProducerDumpResponse(value) => { + Body::FbsProducerDumpResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsProducerGetStatsResponse(value) => { + Body::FbsProducerGetStatsResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsConsumerDumpResponse(value) => { + Body::FbsConsumerDumpResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsConsumerGetStatsResponse(value) => { + Body::FbsConsumerGetStatsResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsConsumerSetPreferredLayersResponse(value) => { + Body::FbsConsumerSetPreferredLayersResponse( + ::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + ), + ) + } + + BodyRef::FbsConsumerSetPriorityResponse(value) => { + Body::FbsConsumerSetPriorityResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsDataProducerDumpResponse(value) => { + Body::FbsDataProducerDumpResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsDataProducerGetStatsResponse(value) => { + Body::FbsDataProducerGetStatsResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsDataConsumerGetBufferedAmountResponse(value) => { + Body::FbsDataConsumerGetBufferedAmountResponse( + ::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + ), + ) + } + + BodyRef::FbsDataConsumerDumpResponse(value) => { + Body::FbsDataConsumerDumpResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + BodyRef::FbsDataConsumerGetStatsResponse(value) => { + Body::FbsDataConsumerGetStatsResponse(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + }) + } + } + + impl<'a> ::planus::TableReadUnion<'a> for BodyRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + field_offset: usize, + tag: u8, + ) -> ::core::result::Result { + match tag { + 1 => ::core::result::Result::Ok(Self::FbsWorkerDumpResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 2 => ::core::result::Result::Ok(Self::FbsWorkerResourceUsageResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 3 => ::core::result::Result::Ok(Self::FbsWebRtcServerDumpResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 4 => ::core::result::Result::Ok(Self::FbsRouterDumpResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 5 => ::core::result::Result::Ok(Self::FbsTransportProduceResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 6 => ::core::result::Result::Ok(Self::FbsTransportConsumeResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 7 => ::core::result::Result::Ok(Self::FbsTransportRestartIceResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 8 => ::core::result::Result::Ok(Self::FbsPlainTransportConnectResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 9 => ::core::result::Result::Ok(Self::FbsPlainTransportDumpResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 10 => ::core::result::Result::Ok(Self::FbsPlainTransportGetStatsResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 11 => ::core::result::Result::Ok(Self::FbsPipeTransportConnectResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 12 => ::core::result::Result::Ok(Self::FbsPipeTransportDumpResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 13 => ::core::result::Result::Ok(Self::FbsPipeTransportGetStatsResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 14 => ::core::result::Result::Ok(Self::FbsDirectTransportDumpResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 15 => ::core::result::Result::Ok(Self::FbsDirectTransportGetStatsResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 16 => ::core::result::Result::Ok(Self::FbsWebRtcTransportConnectResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 17 => ::core::result::Result::Ok(Self::FbsWebRtcTransportDumpResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 18 => ::core::result::Result::Ok(Self::FbsWebRtcTransportGetStatsResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 19 => ::core::result::Result::Ok(Self::FbsProducerDumpResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 20 => ::core::result::Result::Ok(Self::FbsProducerGetStatsResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 21 => ::core::result::Result::Ok(Self::FbsConsumerDumpResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 22 => ::core::result::Result::Ok(Self::FbsConsumerGetStatsResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 23 => { + ::core::result::Result::Ok(Self::FbsConsumerSetPreferredLayersResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )) + } + 24 => ::core::result::Result::Ok(Self::FbsConsumerSetPriorityResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 25 => ::core::result::Result::Ok(Self::FbsDataProducerDumpResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 26 => ::core::result::Result::Ok(Self::FbsDataProducerGetStatsResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 27 => ::core::result::Result::Ok( + Self::FbsDataConsumerGetBufferedAmountResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + ), + ), + 28 => ::core::result::Result::Ok(Self::FbsDataConsumerDumpResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 29 => ::core::result::Result::Ok(Self::FbsDataConsumerGetStatsResponse( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + _ => ::core::result::Result::Err( + ::planus::errors::ErrorKind::UnknownUnionTag { tag }, + ), + } + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct Response { + pub id: u32, + pub accepted: bool, + pub body: ::core::option::Option, + pub error: ::core::option::Option<::planus::alloc::string::String>, + pub reason: ::core::option::Option<::planus::alloc::string::String>, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for Response { + fn default() -> Self { + Self { + id: 0, + accepted: false, + body: ::core::default::Default::default(), + error: ::core::default::Default::default(), + reason: ::core::default::Default::default(), + } + } + } + + impl Response { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_id: impl ::planus::WriteAsDefault, + field_accepted: impl ::planus::WriteAsDefault, + field_body: impl ::planus::WriteAsOptionalUnion, + field_error: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + field_reason: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + ) -> ::planus::Offset { + let prepared_id = field_id.prepare(builder, &0); + + let prepared_accepted = field_accepted.prepare(builder, &false); + + let prepared_body = field_body.prepare(builder); + + let prepared_error = field_error.prepare(builder); + + let prepared_reason = field_reason.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<14, 18>::new(builder); + + if prepared_id.is_some() { + table_writer.calculate_size::(2); + } + if prepared_accepted.is_some() { + table_writer.calculate_size::(4); + } + if prepared_body.is_some() { + table_writer.calculate_size::(6); + table_writer.calculate_size::<::planus::Offset>(8); + } + if prepared_error.is_some() { + table_writer.calculate_size::<::planus::Offset>(10); + } + if prepared_reason.is_some() { + table_writer.calculate_size::<::planus::Offset>(12); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_id) = prepared_id { + table_writer.write::<_, _, 4>(0, &prepared_id); + } + if let ::core::option::Option::Some(prepared_body) = prepared_body { + table_writer.write::<_, _, 4>(3, &prepared_body.offset()); + } + if let ::core::option::Option::Some(prepared_error) = prepared_error { + table_writer.write::<_, _, 4>(4, &prepared_error); + } + if let ::core::option::Option::Some(prepared_reason) = prepared_reason { + table_writer.write::<_, _, 4>(5, &prepared_reason); + } + if let ::core::option::Option::Some(prepared_accepted) = prepared_accepted { + table_writer.write::<_, _, 1>(1, &prepared_accepted); + } + if let ::core::option::Option::Some(prepared_body) = prepared_body { + table_writer.write::<_, _, 1>(2, &prepared_body.tag()); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Response { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Response { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Response { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Response::create( + builder, + &self.id, + &self.accepted, + &self.body, + &self.error, + &self.reason, + ) + } + } + + #[derive(Copy, Clone)] + pub struct ResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ResponseRef<'a> { + pub fn id(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(0, "Response", "id")?.unwrap_or(0)) + } + + pub fn accepted(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(1, "Response", "accepted")?.unwrap_or(false), + ) + } + + pub fn body(&self) -> ::planus::Result<::core::option::Option>> { + self.0.access_union(2, "Response", "body") + } + + pub fn error( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(4, "Response", "error") + } + + pub fn reason( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(5, "Response", "reason") + } + } + + impl<'a> ::core::fmt::Debug for ResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ResponseRef"); + f.field("id", &self.id()); + f.field("accepted", &self.accepted()); + if let ::core::option::Option::Some(field_body) = self.body().transpose() { + f.field("body", &field_body); + } + if let ::core::option::Option::Some(field_error) = self.error().transpose() { + f.field("error", &field_error); + } + if let ::core::option::Option::Some(field_reason) = self.reason().transpose() { + f.field("reason", &field_reason); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Response { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + id: ::core::convert::TryInto::try_into(value.id()?)?, + accepted: ::core::convert::TryInto::try_into(value.accepted()?)?, + body: if let ::core::option::Option::Some(body) = value.body()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(body)?) + } else { + ::core::option::Option::None + }, + error: if let ::core::option::Option::Some(error) = value.error()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(error)?) + } else { + ::core::option::Option::None + }, + reason: if let ::core::option::Option::Some(reason) = value.reason()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + reason, + )?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Response { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ResponseRef]", "read_as_root", 0) + }) + } + } + } + pub mod worker { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ChannelMessageHandlers { + pub channel_request_handlers: ::core::option::Option< + ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + >, + pub channel_notification_handlers: ::core::option::Option< + ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + >, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for ChannelMessageHandlers { + fn default() -> Self { + Self { + channel_request_handlers: ::core::default::Default::default(), + channel_notification_handlers: ::core::default::Default::default(), + } + } + } + + impl ChannelMessageHandlers { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_channel_request_handlers: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_channel_notification_handlers: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_channel_request_handlers = + field_channel_request_handlers.prepare(builder); + + let prepared_channel_notification_handlers = + field_channel_notification_handlers.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + if prepared_channel_request_handlers.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(2); + } + if prepared_channel_notification_handlers.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(4); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_channel_request_handlers) = + prepared_channel_request_handlers + { + table_writer.write::<_, _, 4>(0, &prepared_channel_request_handlers); + } + if let ::core::option::Option::Some( + prepared_channel_notification_handlers, + ) = prepared_channel_notification_handlers + { + table_writer + .write::<_, _, 4>(1, &prepared_channel_notification_handlers); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ChannelMessageHandlers { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for ChannelMessageHandlers + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ChannelMessageHandlers { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ChannelMessageHandlers::create( + builder, + &self.channel_request_handlers, + &self.channel_notification_handlers, + ) + } + } + + #[derive(Copy, Clone)] + pub struct ChannelMessageHandlersRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ChannelMessageHandlersRef<'a> { + pub fn channel_request_handlers( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + >, + > { + self.0 + .access(0, "ChannelMessageHandlers", "channel_request_handlers") + } + + pub fn channel_notification_handlers( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + >, + > { + self.0 + .access(1, "ChannelMessageHandlers", "channel_notification_handlers") + } + } + + impl<'a> ::core::fmt::Debug for ChannelMessageHandlersRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ChannelMessageHandlersRef"); + if let ::core::option::Option::Some(field_channel_request_handlers) = + self.channel_request_handlers().transpose() + { + f.field("channel_request_handlers", &field_channel_request_handlers); + } + if let ::core::option::Option::Some(field_channel_notification_handlers) = + self.channel_notification_handlers().transpose() + { + f.field( + "channel_notification_handlers", + &field_channel_notification_handlers, + ); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ChannelMessageHandlers { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ChannelMessageHandlersRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + channel_request_handlers: if let ::core::option::Option::Some( + channel_request_handlers, + ) = value.channel_request_handlers()? + { + ::core::option::Option::Some(channel_request_handlers.to_vec_result()?) + } else { + ::core::option::Option::None + }, + channel_notification_handlers: if let ::core::option::Option::Some( + channel_notification_handlers, + ) = + value.channel_notification_handlers()? + { + ::core::option::Option::Some( + channel_notification_handlers.to_vec_result()?, + ) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ChannelMessageHandlersRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ChannelMessageHandlersRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ChannelMessageHandlersRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ChannelMessageHandlers { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ChannelMessageHandlersRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[ChannelMessageHandlersRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct DumpResponse { + pub pid: u32, + pub web_rtc_server_ids: ::core::option::Option< + ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + >, + pub router_ids: ::core::option::Option< + ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + >, + pub channel_message_handlers: ::core::option::Option< + ::planus::alloc::boxed::Box, + >, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for DumpResponse { + fn default() -> Self { + Self { + pid: 0, + web_rtc_server_ids: ::core::default::Default::default(), + router_ids: ::core::default::Default::default(), + channel_message_handlers: ::core::default::Default::default(), + } + } + } + + impl DumpResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_pid: impl ::planus::WriteAsDefault, + field_web_rtc_server_ids: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_router_ids: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_channel_message_handlers: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_pid = field_pid.prepare(builder, &0); + + let prepared_web_rtc_server_ids = field_web_rtc_server_ids.prepare(builder); + + let prepared_router_ids = field_router_ids.prepare(builder); + + let prepared_channel_message_handlers = + field_channel_message_handlers.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<10, 16>::new(builder); + + if prepared_pid.is_some() { + table_writer.calculate_size::(2); + } + if prepared_web_rtc_server_ids.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(4); + } + if prepared_router_ids.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(6); + } + if prepared_channel_message_handlers.is_some() { + table_writer + .calculate_size::<::planus::Offset>(8); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_pid) = prepared_pid { + table_writer.write::<_, _, 4>(0, &prepared_pid); + } + if let ::core::option::Option::Some(prepared_web_rtc_server_ids) = + prepared_web_rtc_server_ids + { + table_writer.write::<_, _, 4>(1, &prepared_web_rtc_server_ids); + } + if let ::core::option::Option::Some(prepared_router_ids) = + prepared_router_ids + { + table_writer.write::<_, _, 4>(2, &prepared_router_ids); + } + if let ::core::option::Option::Some(prepared_channel_message_handlers) = + prepared_channel_message_handlers + { + table_writer.write::<_, _, 4>(3, &prepared_channel_message_handlers); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for DumpResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + DumpResponse::create( + builder, + &self.pid, + &self.web_rtc_server_ids, + &self.router_ids, + &self.channel_message_handlers, + ) + } + } + + #[derive(Copy, Clone)] + pub struct DumpResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DumpResponseRef<'a> { + pub fn pid(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "DumpResponse", "pid")?.unwrap_or(0), + ) + } + + pub fn web_rtc_server_ids( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + >, + > { + self.0.access(1, "DumpResponse", "web_rtc_server_ids") + } + + pub fn router_ids( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + >, + > { + self.0.access(2, "DumpResponse", "router_ids") + } + + pub fn channel_message_handlers( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(3, "DumpResponse", "channel_message_handlers") + } + } + + impl<'a> ::core::fmt::Debug for DumpResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DumpResponseRef"); + f.field("pid", &self.pid()); + if let ::core::option::Option::Some(field_web_rtc_server_ids) = + self.web_rtc_server_ids().transpose() + { + f.field("web_rtc_server_ids", &field_web_rtc_server_ids); + } + if let ::core::option::Option::Some(field_router_ids) = + self.router_ids().transpose() + { + f.field("router_ids", &field_router_ids); + } + if let ::core::option::Option::Some(field_channel_message_handlers) = + self.channel_message_handlers().transpose() + { + f.field("channel_message_handlers", &field_channel_message_handlers); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for DumpResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DumpResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + pid: ::core::convert::TryInto::try_into(value.pid()?)?, + web_rtc_server_ids: if let ::core::option::Option::Some( + web_rtc_server_ids, + ) = value.web_rtc_server_ids()? + { + ::core::option::Option::Some(web_rtc_server_ids.to_vec_result()?) + } else { + ::core::option::Option::None + }, + router_ids: if let ::core::option::Option::Some(router_ids) = + value.router_ids()? + { + ::core::option::Option::Some(router_ids.to_vec_result()?) + } else { + ::core::option::Option::None + }, + channel_message_handlers: if let ::core::option::Option::Some( + channel_message_handlers, + ) = value.channel_message_handlers()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(channel_message_handlers)?, + )) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DumpResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DumpResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DumpResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for DumpResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DumpResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[DumpResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ResourceUsageResponse { + pub ru_utime: u64, + pub ru_stime: u64, + pub ru_maxrss: u64, + pub ru_ixrss: u64, + pub ru_idrss: u64, + pub ru_isrss: u64, + pub ru_minflt: u64, + pub ru_majflt: u64, + pub ru_nswap: u64, + pub ru_inblock: u64, + pub ru_oublock: u64, + pub ru_msgsnd: u64, + pub ru_msgrcv: u64, + pub ru_nsignals: u64, + pub ru_nvcsw: u64, + pub ru_nivcsw: u64, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for ResourceUsageResponse { + fn default() -> Self { + Self { + ru_utime: 0, + ru_stime: 0, + ru_maxrss: 0, + ru_ixrss: 0, + ru_idrss: 0, + ru_isrss: 0, + ru_minflt: 0, + ru_majflt: 0, + ru_nswap: 0, + ru_inblock: 0, + ru_oublock: 0, + ru_msgsnd: 0, + ru_msgrcv: 0, + ru_nsignals: 0, + ru_nvcsw: 0, + ru_nivcsw: 0, + } + } + } + + impl ResourceUsageResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ru_utime: impl ::planus::WriteAsDefault, + field_ru_stime: impl ::planus::WriteAsDefault, + field_ru_maxrss: impl ::planus::WriteAsDefault, + field_ru_ixrss: impl ::planus::WriteAsDefault, + field_ru_idrss: impl ::planus::WriteAsDefault, + field_ru_isrss: impl ::planus::WriteAsDefault, + field_ru_minflt: impl ::planus::WriteAsDefault, + field_ru_majflt: impl ::planus::WriteAsDefault, + field_ru_nswap: impl ::planus::WriteAsDefault, + field_ru_inblock: impl ::planus::WriteAsDefault, + field_ru_oublock: impl ::planus::WriteAsDefault, + field_ru_msgsnd: impl ::planus::WriteAsDefault, + field_ru_msgrcv: impl ::planus::WriteAsDefault, + field_ru_nsignals: impl ::planus::WriteAsDefault, + field_ru_nvcsw: impl ::planus::WriteAsDefault, + field_ru_nivcsw: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_ru_utime = field_ru_utime.prepare(builder, &0); + + let prepared_ru_stime = field_ru_stime.prepare(builder, &0); + + let prepared_ru_maxrss = field_ru_maxrss.prepare(builder, &0); + + let prepared_ru_ixrss = field_ru_ixrss.prepare(builder, &0); + + let prepared_ru_idrss = field_ru_idrss.prepare(builder, &0); + + let prepared_ru_isrss = field_ru_isrss.prepare(builder, &0); + + let prepared_ru_minflt = field_ru_minflt.prepare(builder, &0); + + let prepared_ru_majflt = field_ru_majflt.prepare(builder, &0); + + let prepared_ru_nswap = field_ru_nswap.prepare(builder, &0); + + let prepared_ru_inblock = field_ru_inblock.prepare(builder, &0); + + let prepared_ru_oublock = field_ru_oublock.prepare(builder, &0); + + let prepared_ru_msgsnd = field_ru_msgsnd.prepare(builder, &0); + + let prepared_ru_msgrcv = field_ru_msgrcv.prepare(builder, &0); + + let prepared_ru_nsignals = field_ru_nsignals.prepare(builder, &0); + + let prepared_ru_nvcsw = field_ru_nvcsw.prepare(builder, &0); + + let prepared_ru_nivcsw = field_ru_nivcsw.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<34, 128>::new(builder); + + if prepared_ru_utime.is_some() { + table_writer.calculate_size::(2); + } + if prepared_ru_stime.is_some() { + table_writer.calculate_size::(4); + } + if prepared_ru_maxrss.is_some() { + table_writer.calculate_size::(6); + } + if prepared_ru_ixrss.is_some() { + table_writer.calculate_size::(8); + } + if prepared_ru_idrss.is_some() { + table_writer.calculate_size::(10); + } + if prepared_ru_isrss.is_some() { + table_writer.calculate_size::(12); + } + if prepared_ru_minflt.is_some() { + table_writer.calculate_size::(14); + } + if prepared_ru_majflt.is_some() { + table_writer.calculate_size::(16); + } + if prepared_ru_nswap.is_some() { + table_writer.calculate_size::(18); + } + if prepared_ru_inblock.is_some() { + table_writer.calculate_size::(20); + } + if prepared_ru_oublock.is_some() { + table_writer.calculate_size::(22); + } + if prepared_ru_msgsnd.is_some() { + table_writer.calculate_size::(24); + } + if prepared_ru_msgrcv.is_some() { + table_writer.calculate_size::(26); + } + if prepared_ru_nsignals.is_some() { + table_writer.calculate_size::(28); + } + if prepared_ru_nvcsw.is_some() { + table_writer.calculate_size::(30); + } + if prepared_ru_nivcsw.is_some() { + table_writer.calculate_size::(32); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_ru_utime) = prepared_ru_utime { + table_writer.write::<_, _, 8>(0, &prepared_ru_utime); + } + if let ::core::option::Option::Some(prepared_ru_stime) = prepared_ru_stime { + table_writer.write::<_, _, 8>(1, &prepared_ru_stime); + } + if let ::core::option::Option::Some(prepared_ru_maxrss) = prepared_ru_maxrss + { + table_writer.write::<_, _, 8>(2, &prepared_ru_maxrss); + } + if let ::core::option::Option::Some(prepared_ru_ixrss) = prepared_ru_ixrss { + table_writer.write::<_, _, 8>(3, &prepared_ru_ixrss); + } + if let ::core::option::Option::Some(prepared_ru_idrss) = prepared_ru_idrss { + table_writer.write::<_, _, 8>(4, &prepared_ru_idrss); + } + if let ::core::option::Option::Some(prepared_ru_isrss) = prepared_ru_isrss { + table_writer.write::<_, _, 8>(5, &prepared_ru_isrss); + } + if let ::core::option::Option::Some(prepared_ru_minflt) = prepared_ru_minflt + { + table_writer.write::<_, _, 8>(6, &prepared_ru_minflt); + } + if let ::core::option::Option::Some(prepared_ru_majflt) = prepared_ru_majflt + { + table_writer.write::<_, _, 8>(7, &prepared_ru_majflt); + } + if let ::core::option::Option::Some(prepared_ru_nswap) = prepared_ru_nswap { + table_writer.write::<_, _, 8>(8, &prepared_ru_nswap); + } + if let ::core::option::Option::Some(prepared_ru_inblock) = + prepared_ru_inblock + { + table_writer.write::<_, _, 8>(9, &prepared_ru_inblock); + } + if let ::core::option::Option::Some(prepared_ru_oublock) = + prepared_ru_oublock + { + table_writer.write::<_, _, 8>(10, &prepared_ru_oublock); + } + if let ::core::option::Option::Some(prepared_ru_msgsnd) = prepared_ru_msgsnd + { + table_writer.write::<_, _, 8>(11, &prepared_ru_msgsnd); + } + if let ::core::option::Option::Some(prepared_ru_msgrcv) = prepared_ru_msgrcv + { + table_writer.write::<_, _, 8>(12, &prepared_ru_msgrcv); + } + if let ::core::option::Option::Some(prepared_ru_nsignals) = + prepared_ru_nsignals + { + table_writer.write::<_, _, 8>(13, &prepared_ru_nsignals); + } + if let ::core::option::Option::Some(prepared_ru_nvcsw) = prepared_ru_nvcsw { + table_writer.write::<_, _, 8>(14, &prepared_ru_nvcsw); + } + if let ::core::option::Option::Some(prepared_ru_nivcsw) = prepared_ru_nivcsw + { + table_writer.write::<_, _, 8>(15, &prepared_ru_nivcsw); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ResourceUsageResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ResourceUsageResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ResourceUsageResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ResourceUsageResponse::create( + builder, + &self.ru_utime, + &self.ru_stime, + &self.ru_maxrss, + &self.ru_ixrss, + &self.ru_idrss, + &self.ru_isrss, + &self.ru_minflt, + &self.ru_majflt, + &self.ru_nswap, + &self.ru_inblock, + &self.ru_oublock, + &self.ru_msgsnd, + &self.ru_msgrcv, + &self.ru_nsignals, + &self.ru_nvcsw, + &self.ru_nivcsw, + ) + } + } + + #[derive(Copy, Clone)] + pub struct ResourceUsageResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ResourceUsageResponseRef<'a> { + pub fn ru_utime(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "ResourceUsageResponse", "ru_utime")? + .unwrap_or(0), + ) + } + + pub fn ru_stime(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "ResourceUsageResponse", "ru_stime")? + .unwrap_or(0), + ) + } + + pub fn ru_maxrss(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "ResourceUsageResponse", "ru_maxrss")? + .unwrap_or(0), + ) + } + + pub fn ru_ixrss(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(3, "ResourceUsageResponse", "ru_ixrss")? + .unwrap_or(0), + ) + } + + pub fn ru_idrss(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(4, "ResourceUsageResponse", "ru_idrss")? + .unwrap_or(0), + ) + } + + pub fn ru_isrss(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(5, "ResourceUsageResponse", "ru_isrss")? + .unwrap_or(0), + ) + } + + pub fn ru_minflt(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(6, "ResourceUsageResponse", "ru_minflt")? + .unwrap_or(0), + ) + } + + pub fn ru_majflt(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(7, "ResourceUsageResponse", "ru_majflt")? + .unwrap_or(0), + ) + } + + pub fn ru_nswap(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(8, "ResourceUsageResponse", "ru_nswap")? + .unwrap_or(0), + ) + } + + pub fn ru_inblock(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(9, "ResourceUsageResponse", "ru_inblock")? + .unwrap_or(0), + ) + } + + pub fn ru_oublock(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(10, "ResourceUsageResponse", "ru_oublock")? + .unwrap_or(0), + ) + } + + pub fn ru_msgsnd(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(11, "ResourceUsageResponse", "ru_msgsnd")? + .unwrap_or(0), + ) + } + + pub fn ru_msgrcv(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(12, "ResourceUsageResponse", "ru_msgrcv")? + .unwrap_or(0), + ) + } + + pub fn ru_nsignals(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(13, "ResourceUsageResponse", "ru_nsignals")? + .unwrap_or(0), + ) + } + + pub fn ru_nvcsw(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(14, "ResourceUsageResponse", "ru_nvcsw")? + .unwrap_or(0), + ) + } + + pub fn ru_nivcsw(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(15, "ResourceUsageResponse", "ru_nivcsw")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for ResourceUsageResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ResourceUsageResponseRef"); + f.field("ru_utime", &self.ru_utime()); + f.field("ru_stime", &self.ru_stime()); + f.field("ru_maxrss", &self.ru_maxrss()); + f.field("ru_ixrss", &self.ru_ixrss()); + f.field("ru_idrss", &self.ru_idrss()); + f.field("ru_isrss", &self.ru_isrss()); + f.field("ru_minflt", &self.ru_minflt()); + f.field("ru_majflt", &self.ru_majflt()); + f.field("ru_nswap", &self.ru_nswap()); + f.field("ru_inblock", &self.ru_inblock()); + f.field("ru_oublock", &self.ru_oublock()); + f.field("ru_msgsnd", &self.ru_msgsnd()); + f.field("ru_msgrcv", &self.ru_msgrcv()); + f.field("ru_nsignals", &self.ru_nsignals()); + f.field("ru_nvcsw", &self.ru_nvcsw()); + f.field("ru_nivcsw", &self.ru_nivcsw()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ResourceUsageResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ResourceUsageResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ru_utime: ::core::convert::TryInto::try_into(value.ru_utime()?)?, + ru_stime: ::core::convert::TryInto::try_into(value.ru_stime()?)?, + ru_maxrss: ::core::convert::TryInto::try_into(value.ru_maxrss()?)?, + ru_ixrss: ::core::convert::TryInto::try_into(value.ru_ixrss()?)?, + ru_idrss: ::core::convert::TryInto::try_into(value.ru_idrss()?)?, + ru_isrss: ::core::convert::TryInto::try_into(value.ru_isrss()?)?, + ru_minflt: ::core::convert::TryInto::try_into(value.ru_minflt()?)?, + ru_majflt: ::core::convert::TryInto::try_into(value.ru_majflt()?)?, + ru_nswap: ::core::convert::TryInto::try_into(value.ru_nswap()?)?, + ru_inblock: ::core::convert::TryInto::try_into(value.ru_inblock()?)?, + ru_oublock: ::core::convert::TryInto::try_into(value.ru_oublock()?)?, + ru_msgsnd: ::core::convert::TryInto::try_into(value.ru_msgsnd()?)?, + ru_msgrcv: ::core::convert::TryInto::try_into(value.ru_msgrcv()?)?, + ru_nsignals: ::core::convert::TryInto::try_into(value.ru_nsignals()?)?, + ru_nvcsw: ::core::convert::TryInto::try_into(value.ru_nvcsw()?)?, + ru_nivcsw: ::core::convert::TryInto::try_into(value.ru_nivcsw()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ResourceUsageResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ResourceUsageResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ResourceUsageResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ResourceUsageResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ResourceUsageResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[ResourceUsageResponseRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct UpdateSettingsRequest { + pub log_level: ::core::option::Option<::planus::alloc::string::String>, + pub log_tags: ::core::option::Option< + ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + >, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for UpdateSettingsRequest { + fn default() -> Self { + Self { + log_level: ::core::default::Default::default(), + log_tags: ::core::default::Default::default(), + } + } + } + + impl UpdateSettingsRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_log_level: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + field_log_tags: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_log_level = field_log_level.prepare(builder); + + let prepared_log_tags = field_log_tags.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + if prepared_log_level.is_some() { + table_writer.calculate_size::<::planus::Offset>(2); + } + if prepared_log_tags.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(4); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_log_level) = prepared_log_level + { + table_writer.write::<_, _, 4>(0, &prepared_log_level); + } + if let ::core::option::Option::Some(prepared_log_tags) = prepared_log_tags { + table_writer.write::<_, _, 4>(1, &prepared_log_tags); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for UpdateSettingsRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for UpdateSettingsRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for UpdateSettingsRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + UpdateSettingsRequest::create(builder, &self.log_level, &self.log_tags) + } + } + + #[derive(Copy, Clone)] + pub struct UpdateSettingsRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> UpdateSettingsRequestRef<'a> { + pub fn log_level( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(0, "UpdateSettingsRequest", "log_level") + } + + pub fn log_tags( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + >, + > { + self.0.access(1, "UpdateSettingsRequest", "log_tags") + } + } + + impl<'a> ::core::fmt::Debug for UpdateSettingsRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("UpdateSettingsRequestRef"); + if let ::core::option::Option::Some(field_log_level) = + self.log_level().transpose() + { + f.field("log_level", &field_log_level); + } + if let ::core::option::Option::Some(field_log_tags) = + self.log_tags().transpose() + { + f.field("log_tags", &field_log_tags); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for UpdateSettingsRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: UpdateSettingsRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + log_level: if let ::core::option::Option::Some(log_level) = + value.log_level()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + log_level, + )?) + } else { + ::core::option::Option::None + }, + log_tags: if let ::core::option::Option::Some(log_tags) = + value.log_tags()? + { + ::core::option::Option::Some(log_tags.to_vec_result()?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for UpdateSettingsRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for UpdateSettingsRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[UpdateSettingsRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for UpdateSettingsRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for UpdateSettingsRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[UpdateSettingsRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CreateWebRtcServerRequest { + pub web_rtc_server_id: ::planus::alloc::string::String, + pub listen_infos: ::core::option::Option< + ::planus::alloc::vec::Vec, + >, + } + + impl CreateWebRtcServerRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_web_rtc_server_id: impl ::planus::WriteAs<::planus::Offset>, + field_listen_infos: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_web_rtc_server_id = field_web_rtc_server_id.prepare(builder); + + let prepared_listen_infos = field_listen_infos.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_listen_infos.is_some() { + table_writer.calculate_size::<::planus::Offset< + [::planus::Offset], + >>(4); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_web_rtc_server_id); + if let ::core::option::Option::Some(prepared_listen_infos) = + prepared_listen_infos + { + table_writer.write::<_, _, 4>(1, &prepared_listen_infos); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for CreateWebRtcServerRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for CreateWebRtcServerRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CreateWebRtcServerRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CreateWebRtcServerRequest::create( + builder, + &self.web_rtc_server_id, + &self.listen_infos, + ) + } + } + + #[derive(Copy, Clone)] + pub struct CreateWebRtcServerRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CreateWebRtcServerRequestRef<'a> { + pub fn web_rtc_server_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "CreateWebRtcServerRequest", "web_rtc_server_id") + } + + pub fn listen_infos( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector< + 'a, + ::planus::Result>, + >, + >, + > { + self.0 + .access(1, "CreateWebRtcServerRequest", "listen_infos") + } + } + + impl<'a> ::core::fmt::Debug for CreateWebRtcServerRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CreateWebRtcServerRequestRef"); + f.field("web_rtc_server_id", &self.web_rtc_server_id()); + if let ::core::option::Option::Some(field_listen_infos) = + self.listen_infos().transpose() + { + f.field("listen_infos", &field_listen_infos); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for CreateWebRtcServerRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: CreateWebRtcServerRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + web_rtc_server_id: ::core::convert::TryInto::try_into( + value.web_rtc_server_id()?, + )?, + listen_infos: if let ::core::option::Option::Some(listen_infos) = + value.listen_infos()? + { + ::core::option::Option::Some(listen_infos.to_vec_result()?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CreateWebRtcServerRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CreateWebRtcServerRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CreateWebRtcServerRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for CreateWebRtcServerRequest + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CreateWebRtcServerRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[CreateWebRtcServerRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CloseWebRtcServerRequest { + pub web_rtc_server_id: ::planus::alloc::string::String, + } + + impl CloseWebRtcServerRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_web_rtc_server_id: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_web_rtc_server_id = field_web_rtc_server_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_web_rtc_server_id); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for CloseWebRtcServerRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for CloseWebRtcServerRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CloseWebRtcServerRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CloseWebRtcServerRequest::create(builder, &self.web_rtc_server_id) + } + } + + #[derive(Copy, Clone)] + pub struct CloseWebRtcServerRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CloseWebRtcServerRequestRef<'a> { + pub fn web_rtc_server_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "CloseWebRtcServerRequest", "web_rtc_server_id") + } + } + + impl<'a> ::core::fmt::Debug for CloseWebRtcServerRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CloseWebRtcServerRequestRef"); + f.field("web_rtc_server_id", &self.web_rtc_server_id()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for CloseWebRtcServerRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: CloseWebRtcServerRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + web_rtc_server_id: ::core::convert::TryInto::try_into( + value.web_rtc_server_id()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CloseWebRtcServerRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CloseWebRtcServerRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CloseWebRtcServerRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for CloseWebRtcServerRequest + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CloseWebRtcServerRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[CloseWebRtcServerRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CreateRouterRequest { + pub router_id: ::planus::alloc::string::String, + } + + impl CreateRouterRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_router_id: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_router_id = field_router_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_router_id); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for CreateRouterRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for CreateRouterRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CreateRouterRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CreateRouterRequest::create(builder, &self.router_id) + } + } + + #[derive(Copy, Clone)] + pub struct CreateRouterRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CreateRouterRequestRef<'a> { + pub fn router_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "CreateRouterRequest", "router_id") + } + } + + impl<'a> ::core::fmt::Debug for CreateRouterRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CreateRouterRequestRef"); + f.field("router_id", &self.router_id()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for CreateRouterRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: CreateRouterRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + router_id: ::core::convert::TryInto::try_into(value.router_id()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CreateRouterRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CreateRouterRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CreateRouterRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for CreateRouterRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CreateRouterRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[CreateRouterRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CloseRouterRequest { + pub router_id: ::planus::alloc::string::String, + } + + impl CloseRouterRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_router_id: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_router_id = field_router_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_router_id); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for CloseRouterRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for CloseRouterRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CloseRouterRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CloseRouterRequest::create(builder, &self.router_id) + } + } + + #[derive(Copy, Clone)] + pub struct CloseRouterRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CloseRouterRequestRef<'a> { + pub fn router_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "CloseRouterRequest", "router_id") + } + } + + impl<'a> ::core::fmt::Debug for CloseRouterRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CloseRouterRequestRef"); + f.field("router_id", &self.router_id()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for CloseRouterRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: CloseRouterRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + router_id: ::core::convert::TryInto::try_into(value.router_id()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CloseRouterRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CloseRouterRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CloseRouterRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for CloseRouterRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CloseRouterRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[CloseRouterRequestRef]", "read_as_root", 0) + }) + } + } + } + pub mod router { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct DumpResponse { + pub id: ::planus::alloc::string::String, + pub transport_ids: ::core::option::Option< + ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + >, + pub rtp_observer_ids: ::core::option::Option< + ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + >, + pub map_producer_id_consumer_ids: ::core::option::Option< + ::planus::alloc::vec::Vec, + >, + pub map_consumer_id_producer_id: + ::core::option::Option<::planus::alloc::vec::Vec>, + pub map_producer_id_observer_ids: ::core::option::Option< + ::planus::alloc::vec::Vec, + >, + pub map_data_producer_id_data_consumer_ids: ::core::option::Option< + ::planus::alloc::vec::Vec, + >, + pub map_data_consumer_id_data_producer_id: + ::core::option::Option<::planus::alloc::vec::Vec>, + } + + impl DumpResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_id: impl ::planus::WriteAs<::planus::Offset>, + field_transport_ids: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_rtp_observer_ids: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_map_producer_id_consumer_ids: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_map_consumer_id_producer_id: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_map_producer_id_observer_ids: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_map_data_producer_id_data_consumer_ids: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_map_data_consumer_id_data_producer_id: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_id = field_id.prepare(builder); + + let prepared_transport_ids = field_transport_ids.prepare(builder); + + let prepared_rtp_observer_ids = field_rtp_observer_ids.prepare(builder); + + let prepared_map_producer_id_consumer_ids = + field_map_producer_id_consumer_ids.prepare(builder); + + let prepared_map_consumer_id_producer_id = + field_map_consumer_id_producer_id.prepare(builder); + + let prepared_map_producer_id_observer_ids = + field_map_producer_id_observer_ids.prepare(builder); + + let prepared_map_data_producer_id_data_consumer_ids = + field_map_data_producer_id_data_consumer_ids.prepare(builder); + + let prepared_map_data_consumer_id_data_producer_id = + field_map_data_consumer_id_data_producer_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<18, 32>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_transport_ids.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(4); + } + if prepared_rtp_observer_ids.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(6); + } + if prepared_map_producer_id_consumer_ids.is_some() { + table_writer.calculate_size::<::planus::Offset< + [::planus::Offset], + >>(8); + } + if prepared_map_consumer_id_producer_id.is_some() { + table_writer.calculate_size::<::planus::Offset< + [::planus::Offset], + >>(10); + } + if prepared_map_producer_id_observer_ids.is_some() { + table_writer.calculate_size::<::planus::Offset< + [::planus::Offset], + >>(12); + } + if prepared_map_data_producer_id_data_consumer_ids.is_some() { + table_writer.calculate_size::<::planus::Offset< + [::planus::Offset], + >>(14); + } + if prepared_map_data_consumer_id_data_producer_id.is_some() { + table_writer.calculate_size::<::planus::Offset< + [::planus::Offset], + >>(16); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_id); + if let ::core::option::Option::Some(prepared_transport_ids) = + prepared_transport_ids + { + table_writer.write::<_, _, 4>(1, &prepared_transport_ids); + } + if let ::core::option::Option::Some(prepared_rtp_observer_ids) = + prepared_rtp_observer_ids + { + table_writer.write::<_, _, 4>(2, &prepared_rtp_observer_ids); + } + if let ::core::option::Option::Some(prepared_map_producer_id_consumer_ids) = + prepared_map_producer_id_consumer_ids + { + table_writer + .write::<_, _, 4>(3, &prepared_map_producer_id_consumer_ids); + } + if let ::core::option::Option::Some(prepared_map_consumer_id_producer_id) = + prepared_map_consumer_id_producer_id + { + table_writer.write::<_, _, 4>(4, &prepared_map_consumer_id_producer_id); + } + if let ::core::option::Option::Some(prepared_map_producer_id_observer_ids) = + prepared_map_producer_id_observer_ids + { + table_writer + .write::<_, _, 4>(5, &prepared_map_producer_id_observer_ids); + } + if let ::core::option::Option::Some( + prepared_map_data_producer_id_data_consumer_ids, + ) = prepared_map_data_producer_id_data_consumer_ids + { + table_writer.write::<_, _, 4>( + 6, + &prepared_map_data_producer_id_data_consumer_ids, + ); + } + if let ::core::option::Option::Some( + prepared_map_data_consumer_id_data_producer_id, + ) = prepared_map_data_consumer_id_data_producer_id + { + table_writer.write::<_, _, 4>( + 7, + &prepared_map_data_consumer_id_data_producer_id, + ); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for DumpResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + DumpResponse::create( + builder, + &self.id, + &self.transport_ids, + &self.rtp_observer_ids, + &self.map_producer_id_consumer_ids, + &self.map_consumer_id_producer_id, + &self.map_producer_id_observer_ids, + &self.map_data_producer_id_data_consumer_ids, + &self.map_data_consumer_id_data_producer_id, + ) + } + } + + #[derive(Copy, Clone)] + pub struct DumpResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DumpResponseRef<'a> { + pub fn id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "DumpResponse", "id") + } + + pub fn transport_ids( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + >, + > { + self.0.access(1, "DumpResponse", "transport_ids") + } + + pub fn rtp_observer_ids( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + >, + > { + self.0.access(2, "DumpResponse", "rtp_observer_ids") + } + + pub fn map_producer_id_consumer_ids( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector< + 'a, + ::planus::Result>, + >, + >, + > { + self.0 + .access(3, "DumpResponse", "map_producer_id_consumer_ids") + } + + pub fn map_consumer_id_producer_id( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result>>, + >, + > { + self.0 + .access(4, "DumpResponse", "map_consumer_id_producer_id") + } + + pub fn map_producer_id_observer_ids( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector< + 'a, + ::planus::Result>, + >, + >, + > { + self.0 + .access(5, "DumpResponse", "map_producer_id_observer_ids") + } + + pub fn map_data_producer_id_data_consumer_ids( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector< + 'a, + ::planus::Result>, + >, + >, + > { + self.0 + .access(6, "DumpResponse", "map_data_producer_id_data_consumer_ids") + } + + pub fn map_data_consumer_id_data_producer_id( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result>>, + >, + > { + self.0 + .access(7, "DumpResponse", "map_data_consumer_id_data_producer_id") + } + } + + impl<'a> ::core::fmt::Debug for DumpResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DumpResponseRef"); + f.field("id", &self.id()); + if let ::core::option::Option::Some(field_transport_ids) = + self.transport_ids().transpose() + { + f.field("transport_ids", &field_transport_ids); + } + if let ::core::option::Option::Some(field_rtp_observer_ids) = + self.rtp_observer_ids().transpose() + { + f.field("rtp_observer_ids", &field_rtp_observer_ids); + } + if let ::core::option::Option::Some(field_map_producer_id_consumer_ids) = + self.map_producer_id_consumer_ids().transpose() + { + f.field( + "map_producer_id_consumer_ids", + &field_map_producer_id_consumer_ids, + ); + } + if let ::core::option::Option::Some(field_map_consumer_id_producer_id) = + self.map_consumer_id_producer_id().transpose() + { + f.field( + "map_consumer_id_producer_id", + &field_map_consumer_id_producer_id, + ); + } + if let ::core::option::Option::Some(field_map_producer_id_observer_ids) = + self.map_producer_id_observer_ids().transpose() + { + f.field( + "map_producer_id_observer_ids", + &field_map_producer_id_observer_ids, + ); + } + if let ::core::option::Option::Some( + field_map_data_producer_id_data_consumer_ids, + ) = self.map_data_producer_id_data_consumer_ids().transpose() + { + f.field( + "map_data_producer_id_data_consumer_ids", + &field_map_data_producer_id_data_consumer_ids, + ); + } + if let ::core::option::Option::Some( + field_map_data_consumer_id_data_producer_id, + ) = self.map_data_consumer_id_data_producer_id().transpose() + { + f.field( + "map_data_consumer_id_data_producer_id", + &field_map_data_consumer_id_data_producer_id, + ); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for DumpResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DumpResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + id: ::core::convert::TryInto::try_into(value.id()?)?, + transport_ids: if let ::core::option::Option::Some(transport_ids) = + value.transport_ids()? + { + ::core::option::Option::Some(transport_ids.to_vec_result()?) + } else { + ::core::option::Option::None + }, + rtp_observer_ids: if let ::core::option::Option::Some(rtp_observer_ids) = + value.rtp_observer_ids()? + { + ::core::option::Option::Some(rtp_observer_ids.to_vec_result()?) + } else { + ::core::option::Option::None + }, + map_producer_id_consumer_ids: if let ::core::option::Option::Some( + map_producer_id_consumer_ids, + ) = value.map_producer_id_consumer_ids()? + { + ::core::option::Option::Some( + map_producer_id_consumer_ids.to_vec_result()?, + ) + } else { + ::core::option::Option::None + }, + map_consumer_id_producer_id: if let ::core::option::Option::Some( + map_consumer_id_producer_id, + ) = value.map_consumer_id_producer_id()? + { + ::core::option::Option::Some( + map_consumer_id_producer_id.to_vec_result()?, + ) + } else { + ::core::option::Option::None + }, + map_producer_id_observer_ids: if let ::core::option::Option::Some( + map_producer_id_observer_ids, + ) = value.map_producer_id_observer_ids()? + { + ::core::option::Option::Some( + map_producer_id_observer_ids.to_vec_result()?, + ) + } else { + ::core::option::Option::None + }, + map_data_producer_id_data_consumer_ids: + if let ::core::option::Option::Some( + map_data_producer_id_data_consumer_ids, + ) = value.map_data_producer_id_data_consumer_ids()? + { + ::core::option::Option::Some( + map_data_producer_id_data_consumer_ids.to_vec_result()?, + ) + } else { + ::core::option::Option::None + }, + map_data_consumer_id_data_producer_id: if let ::core::option::Option::Some( + map_data_consumer_id_data_producer_id, + ) = + value.map_data_consumer_id_data_producer_id()? + { + ::core::option::Option::Some( + map_data_consumer_id_data_producer_id.to_vec_result()?, + ) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DumpResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DumpResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DumpResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for DumpResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DumpResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[DumpResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CreatePipeTransportRequest { + pub transport_id: ::planus::alloc::string::String, + pub options: + ::planus::alloc::boxed::Box, + } + + impl CreatePipeTransportRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_transport_id: impl ::planus::WriteAs<::planus::Offset>, + field_options: impl ::planus::WriteAs< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_transport_id = field_transport_id.prepare(builder); + + let prepared_options = field_options.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_transport_id); + table_writer.write::<_, _, 4>(1, &prepared_options); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for CreatePipeTransportRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for CreatePipeTransportRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CreatePipeTransportRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CreatePipeTransportRequest::create(builder, &self.transport_id, &self.options) + } + } + + #[derive(Copy, Clone)] + pub struct CreatePipeTransportRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CreatePipeTransportRequestRef<'a> { + pub fn transport_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "CreatePipeTransportRequest", "transport_id") + } + + pub fn options( + &self, + ) -> ::planus::Result> + { + self.0 + .access_required(1, "CreatePipeTransportRequest", "options") + } + } + + impl<'a> ::core::fmt::Debug for CreatePipeTransportRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CreatePipeTransportRequestRef"); + f.field("transport_id", &self.transport_id()); + f.field("options", &self.options()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for CreatePipeTransportRequest + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: CreatePipeTransportRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + transport_id: ::core::convert::TryInto::try_into(value.transport_id()?)?, + options: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.options()?)?, + ), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CreatePipeTransportRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CreatePipeTransportRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CreatePipeTransportRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for CreatePipeTransportRequest + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CreatePipeTransportRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[CreatePipeTransportRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CreatePlainTransportRequest { + pub transport_id: ::planus::alloc::string::String, + pub options: + ::planus::alloc::boxed::Box, + } + + impl CreatePlainTransportRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_transport_id: impl ::planus::WriteAs<::planus::Offset>, + field_options: impl ::planus::WriteAs< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_transport_id = field_transport_id.prepare(builder); + + let prepared_options = field_options.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_transport_id); + table_writer.write::<_, _, 4>(1, &prepared_options); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for CreatePlainTransportRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for CreatePlainTransportRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CreatePlainTransportRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CreatePlainTransportRequest::create(builder, &self.transport_id, &self.options) + } + } + + #[derive(Copy, Clone)] + pub struct CreatePlainTransportRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CreatePlainTransportRequestRef<'a> { + pub fn transport_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "CreatePlainTransportRequest", "transport_id") + } + + pub fn options( + &self, + ) -> ::planus::Result> + { + self.0 + .access_required(1, "CreatePlainTransportRequest", "options") + } + } + + impl<'a> ::core::fmt::Debug for CreatePlainTransportRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CreatePlainTransportRequestRef"); + f.field("transport_id", &self.transport_id()); + f.field("options", &self.options()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for CreatePlainTransportRequest + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: CreatePlainTransportRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + transport_id: ::core::convert::TryInto::try_into(value.transport_id()?)?, + options: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.options()?)?, + ), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CreatePlainTransportRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CreatePlainTransportRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CreatePlainTransportRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for CreatePlainTransportRequest + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CreatePlainTransportRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[CreatePlainTransportRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CreateWebRtcTransportRequest { + pub transport_id: ::planus::alloc::string::String, + pub options: + ::planus::alloc::boxed::Box, + } + + impl CreateWebRtcTransportRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_transport_id: impl ::planus::WriteAs<::planus::Offset>, + field_options: impl ::planus::WriteAs< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_transport_id = field_transport_id.prepare(builder); + + let prepared_options = field_options.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_transport_id); + table_writer.write::<_, _, 4>(1, &prepared_options); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for CreateWebRtcTransportRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for CreateWebRtcTransportRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CreateWebRtcTransportRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CreateWebRtcTransportRequest::create(builder, &self.transport_id, &self.options) + } + } + + #[derive(Copy, Clone)] + pub struct CreateWebRtcTransportRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CreateWebRtcTransportRequestRef<'a> { + pub fn transport_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "CreateWebRtcTransportRequest", "transport_id") + } + + pub fn options( + &self, + ) -> ::planus::Result> + { + self.0 + .access_required(1, "CreateWebRtcTransportRequest", "options") + } + } + + impl<'a> ::core::fmt::Debug for CreateWebRtcTransportRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CreateWebRtcTransportRequestRef"); + f.field("transport_id", &self.transport_id()); + f.field("options", &self.options()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for CreateWebRtcTransportRequest + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: CreateWebRtcTransportRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + transport_id: ::core::convert::TryInto::try_into(value.transport_id()?)?, + options: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.options()?)?, + ), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CreateWebRtcTransportRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CreateWebRtcTransportRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CreateWebRtcTransportRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for CreateWebRtcTransportRequest + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CreateWebRtcTransportRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[CreateWebRtcTransportRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CreateDirectTransportRequest { + pub transport_id: ::planus::alloc::string::String, + pub options: + ::planus::alloc::boxed::Box, + } + + impl CreateDirectTransportRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_transport_id: impl ::planus::WriteAs<::planus::Offset>, + field_options: impl ::planus::WriteAs< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_transport_id = field_transport_id.prepare(builder); + + let prepared_options = field_options.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_transport_id); + table_writer.write::<_, _, 4>(1, &prepared_options); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for CreateDirectTransportRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for CreateDirectTransportRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CreateDirectTransportRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CreateDirectTransportRequest::create(builder, &self.transport_id, &self.options) + } + } + + #[derive(Copy, Clone)] + pub struct CreateDirectTransportRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CreateDirectTransportRequestRef<'a> { + pub fn transport_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "CreateDirectTransportRequest", "transport_id") + } + + pub fn options( + &self, + ) -> ::planus::Result> + { + self.0 + .access_required(1, "CreateDirectTransportRequest", "options") + } + } + + impl<'a> ::core::fmt::Debug for CreateDirectTransportRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CreateDirectTransportRequestRef"); + f.field("transport_id", &self.transport_id()); + f.field("options", &self.options()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for CreateDirectTransportRequest + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: CreateDirectTransportRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + transport_id: ::core::convert::TryInto::try_into(value.transport_id()?)?, + options: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.options()?)?, + ), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CreateDirectTransportRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CreateDirectTransportRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CreateDirectTransportRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for CreateDirectTransportRequest + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CreateDirectTransportRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[CreateDirectTransportRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CreateAudioLevelObserverRequest { + pub rtp_observer_id: ::planus::alloc::string::String, + pub options: ::planus::alloc::boxed::Box< + super::audio_level_observer::AudioLevelObserverOptions, + >, + } + + impl CreateAudioLevelObserverRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_rtp_observer_id: impl ::planus::WriteAs<::planus::Offset>, + field_options: impl ::planus::WriteAs< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_rtp_observer_id = field_rtp_observer_id.prepare(builder); + + let prepared_options = field_options.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset< + super::audio_level_observer::AudioLevelObserverOptions, + >>(4); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_rtp_observer_id); + table_writer.write::<_, _, 4>(1, &prepared_options); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for CreateAudioLevelObserverRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for CreateAudioLevelObserverRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CreateAudioLevelObserverRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CreateAudioLevelObserverRequest::create( + builder, + &self.rtp_observer_id, + &self.options, + ) + } + } + + #[derive(Copy, Clone)] + pub struct CreateAudioLevelObserverRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CreateAudioLevelObserverRequestRef<'a> { + pub fn rtp_observer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "CreateAudioLevelObserverRequest", "rtp_observer_id") + } + + pub fn options( + &self, + ) -> ::planus::Result> + { + self.0 + .access_required(1, "CreateAudioLevelObserverRequest", "options") + } + } + + impl<'a> ::core::fmt::Debug for CreateAudioLevelObserverRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CreateAudioLevelObserverRequestRef"); + f.field("rtp_observer_id", &self.rtp_observer_id()); + f.field("options", &self.options()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for CreateAudioLevelObserverRequest + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from( + value: CreateAudioLevelObserverRequestRef<'a>, + ) -> ::planus::Result { + ::core::result::Result::Ok(Self { + rtp_observer_id: ::core::convert::TryInto::try_into( + value.rtp_observer_id()?, + )?, + options: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.options()?)?, + ), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CreateAudioLevelObserverRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CreateAudioLevelObserverRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CreateAudioLevelObserverRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for CreateAudioLevelObserverRequest + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CreateAudioLevelObserverRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[CreateAudioLevelObserverRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CreateActiveSpeakerObserverRequest { + pub active_speaker_observer_id: ::planus::alloc::string::String, + pub options: ::planus::alloc::boxed::Box< + super::active_speaker_observer::ActiveSpeakerObserverOptions, + >, + } + + impl CreateActiveSpeakerObserverRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_active_speaker_observer_id: impl ::planus::WriteAs<::planus::Offset>, + field_options: impl ::planus::WriteAs< + ::planus::Offset< + super::active_speaker_observer::ActiveSpeakerObserverOptions, + >, + >, + ) -> ::planus::Offset { + let prepared_active_speaker_observer_id = + field_active_speaker_observer_id.prepare(builder); + + let prepared_options = field_options.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset< + super::active_speaker_observer::ActiveSpeakerObserverOptions, + >>(4); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_active_speaker_observer_id); + table_writer.write::<_, _, 4>(1, &prepared_options); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for CreateActiveSpeakerObserverRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for CreateActiveSpeakerObserverRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset + for CreateActiveSpeakerObserverRequest + { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CreateActiveSpeakerObserverRequest::create( + builder, + &self.active_speaker_observer_id, + &self.options, + ) + } + } + + #[derive(Copy, Clone)] + pub struct CreateActiveSpeakerObserverRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CreateActiveSpeakerObserverRequestRef<'a> { + pub fn active_speaker_observer_id( + &self, + ) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required( + 0, + "CreateActiveSpeakerObserverRequest", + "active_speaker_observer_id", + ) + } + + pub fn options( + &self, + ) -> ::planus::Result< + super::active_speaker_observer::ActiveSpeakerObserverOptionsRef<'a>, + > { + self.0 + .access_required(1, "CreateActiveSpeakerObserverRequest", "options") + } + } + + impl<'a> ::core::fmt::Debug for CreateActiveSpeakerObserverRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CreateActiveSpeakerObserverRequestRef"); + f.field( + "active_speaker_observer_id", + &self.active_speaker_observer_id(), + ); + f.field("options", &self.options()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for CreateActiveSpeakerObserverRequest + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from( + value: CreateActiveSpeakerObserverRequestRef<'a>, + ) -> ::planus::Result { + ::core::result::Result::Ok(Self { + active_speaker_observer_id: ::core::convert::TryInto::try_into( + value.active_speaker_observer_id()?, + )?, + options: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.options()?)?, + ), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CreateActiveSpeakerObserverRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CreateActiveSpeakerObserverRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CreateActiveSpeakerObserverRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for CreateActiveSpeakerObserverRequest + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CreateActiveSpeakerObserverRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[CreateActiveSpeakerObserverRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CloseTransportRequest { + pub transport_id: ::planus::alloc::string::String, + } + + impl CloseTransportRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_transport_id: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_transport_id = field_transport_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_transport_id); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for CloseTransportRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for CloseTransportRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CloseTransportRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CloseTransportRequest::create(builder, &self.transport_id) + } + } + + #[derive(Copy, Clone)] + pub struct CloseTransportRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CloseTransportRequestRef<'a> { + pub fn transport_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "CloseTransportRequest", "transport_id") + } + } + + impl<'a> ::core::fmt::Debug for CloseTransportRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CloseTransportRequestRef"); + f.field("transport_id", &self.transport_id()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for CloseTransportRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: CloseTransportRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + transport_id: ::core::convert::TryInto::try_into(value.transport_id()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CloseTransportRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CloseTransportRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CloseTransportRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for CloseTransportRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CloseTransportRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[CloseTransportRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct CloseRtpObserverRequest { + pub rtp_observer_id: ::planus::alloc::string::String, + } + + impl CloseRtpObserverRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_rtp_observer_id: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_rtp_observer_id = field_rtp_observer_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_rtp_observer_id); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for CloseRtpObserverRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for CloseRtpObserverRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for CloseRtpObserverRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + CloseRtpObserverRequest::create(builder, &self.rtp_observer_id) + } + } + + #[derive(Copy, Clone)] + pub struct CloseRtpObserverRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> CloseRtpObserverRequestRef<'a> { + pub fn rtp_observer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "CloseRtpObserverRequest", "rtp_observer_id") + } + } + + impl<'a> ::core::fmt::Debug for CloseRtpObserverRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("CloseRtpObserverRequestRef"); + f.field("rtp_observer_id", &self.rtp_observer_id()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for CloseRtpObserverRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: CloseRtpObserverRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + rtp_observer_id: ::core::convert::TryInto::try_into( + value.rtp_observer_id()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for CloseRtpObserverRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for CloseRtpObserverRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[CloseRtpObserverRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for CloseRtpObserverRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for CloseRtpObserverRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[CloseRtpObserverRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + } + pub mod web_rtc_server { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ListenInfo { + pub protocol: super::transport::Protocol, + pub ip: ::planus::alloc::string::String, + pub announced_ip: ::core::option::Option<::planus::alloc::string::String>, + pub port: u16, + } + + impl ListenInfo { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_protocol: impl ::planus::WriteAsDefault< + super::transport::Protocol, + super::transport::Protocol, + >, + field_ip: impl ::planus::WriteAs<::planus::Offset>, + field_announced_ip: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + field_port: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_protocol = + field_protocol.prepare(builder, &super::transport::Protocol::Udp); + + let prepared_ip = field_ip.prepare(builder); + + let prepared_announced_ip = field_announced_ip.prepare(builder); + + let prepared_port = field_port.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<10, 11>::new(builder); + + if prepared_protocol.is_some() { + table_writer.calculate_size::(2); + } + table_writer.calculate_size::<::planus::Offset>(4); + if prepared_announced_ip.is_some() { + table_writer.calculate_size::<::planus::Offset>(6); + } + if prepared_port.is_some() { + table_writer.calculate_size::(8); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(1, &prepared_ip); + if let ::core::option::Option::Some(prepared_announced_ip) = + prepared_announced_ip + { + table_writer.write::<_, _, 4>(2, &prepared_announced_ip); + } + if let ::core::option::Option::Some(prepared_port) = prepared_port { + table_writer.write::<_, _, 2>(3, &prepared_port); + } + if let ::core::option::Option::Some(prepared_protocol) = prepared_protocol { + table_writer.write::<_, _, 1>(0, &prepared_protocol); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ListenInfo { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ListenInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ListenInfo { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ListenInfo::create( + builder, + &self.protocol, + &self.ip, + &self.announced_ip, + &self.port, + ) + } + } + + #[derive(Copy, Clone)] + pub struct ListenInfoRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ListenInfoRef<'a> { + pub fn protocol(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "ListenInfo", "protocol")? + .unwrap_or(super::transport::Protocol::Udp), + ) + } + + pub fn ip(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "ListenInfo", "ip") + } + + pub fn announced_ip( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(2, "ListenInfo", "announced_ip") + } + + pub fn port(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(3, "ListenInfo", "port")?.unwrap_or(0)) + } + } + + impl<'a> ::core::fmt::Debug for ListenInfoRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ListenInfoRef"); + f.field("protocol", &self.protocol()); + f.field("ip", &self.ip()); + if let ::core::option::Option::Some(field_announced_ip) = + self.announced_ip().transpose() + { + f.field("announced_ip", &field_announced_ip); + } + f.field("port", &self.port()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ListenInfo { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ListenInfoRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + protocol: ::core::convert::TryInto::try_into(value.protocol()?)?, + ip: ::core::convert::TryInto::try_into(value.ip()?)?, + announced_ip: if let ::core::option::Option::Some(announced_ip) = + value.announced_ip()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + announced_ip, + )?) + } else { + ::core::option::Option::None + }, + port: ::core::convert::TryInto::try_into(value.port()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ListenInfoRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ListenInfoRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ListenInfoRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ListenInfo { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ListenInfoRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ListenInfoRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct IpPort { + pub ip: ::planus::alloc::string::String, + pub port: u16, + } + + impl IpPort { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ip: impl ::planus::WriteAs<::planus::Offset>, + field_port: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_ip = field_ip.prepare(builder); + + let prepared_port = field_port.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 6>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_port.is_some() { + table_writer.calculate_size::(4); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_ip); + if let ::core::option::Option::Some(prepared_port) = prepared_port { + table_writer.write::<_, _, 2>(1, &prepared_port); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for IpPort { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for IpPort { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for IpPort { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + IpPort::create(builder, &self.ip, &self.port) + } + } + + #[derive(Copy, Clone)] + pub struct IpPortRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> IpPortRef<'a> { + pub fn ip(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "IpPort", "ip") + } + + pub fn port(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(1, "IpPort", "port")?.unwrap_or(0)) + } + } + + impl<'a> ::core::fmt::Debug for IpPortRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("IpPortRef"); + f.field("ip", &self.ip()); + f.field("port", &self.port()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for IpPort { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: IpPortRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ip: ::core::convert::TryInto::try_into(value.ip()?)?, + port: ::core::convert::TryInto::try_into(value.port()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for IpPortRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for IpPortRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[IpPortRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for IpPort { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for IpPortRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[IpPortRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct IceUserNameFragment { + pub local_ice_username_fragment: ::planus::alloc::string::String, + pub web_rtc_transport_id: ::planus::alloc::string::String, + } + + impl IceUserNameFragment { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_local_ice_username_fragment: impl ::planus::WriteAs<::planus::Offset>, + field_web_rtc_transport_id: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_local_ice_username_fragment = + field_local_ice_username_fragment.prepare(builder); + + let prepared_web_rtc_transport_id = field_web_rtc_transport_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_local_ice_username_fragment); + table_writer.write::<_, _, 4>(1, &prepared_web_rtc_transport_id); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for IceUserNameFragment { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for IceUserNameFragment { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for IceUserNameFragment { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + IceUserNameFragment::create( + builder, + &self.local_ice_username_fragment, + &self.web_rtc_transport_id, + ) + } + } + + #[derive(Copy, Clone)] + pub struct IceUserNameFragmentRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> IceUserNameFragmentRef<'a> { + pub fn local_ice_username_fragment( + &self, + ) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "IceUserNameFragment", "local_ice_username_fragment") + } + + pub fn web_rtc_transport_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(1, "IceUserNameFragment", "web_rtc_transport_id") + } + } + + impl<'a> ::core::fmt::Debug for IceUserNameFragmentRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("IceUserNameFragmentRef"); + f.field( + "local_ice_username_fragment", + &self.local_ice_username_fragment(), + ); + f.field("web_rtc_transport_id", &self.web_rtc_transport_id()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for IceUserNameFragment { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: IceUserNameFragmentRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + local_ice_username_fragment: ::core::convert::TryInto::try_into( + value.local_ice_username_fragment()?, + )?, + web_rtc_transport_id: ::core::convert::TryInto::try_into( + value.web_rtc_transport_id()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for IceUserNameFragmentRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for IceUserNameFragmentRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[IceUserNameFragmentRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for IceUserNameFragment { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for IceUserNameFragmentRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[IceUserNameFragmentRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct TupleHash { + pub local_ice_username_fragment: u64, + pub web_rtc_transport_id: ::planus::alloc::string::String, + } + + impl TupleHash { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_local_ice_username_fragment: impl ::planus::WriteAsDefault, + field_web_rtc_transport_id: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_local_ice_username_fragment = + field_local_ice_username_fragment.prepare(builder, &0); + + let prepared_web_rtc_transport_id = field_web_rtc_transport_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 12>::new(builder); + + if prepared_local_ice_username_fragment.is_some() { + table_writer.calculate_size::(2); + } + table_writer.calculate_size::<::planus::Offset>(4); + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_local_ice_username_fragment) = + prepared_local_ice_username_fragment + { + table_writer.write::<_, _, 8>(0, &prepared_local_ice_username_fragment); + } + table_writer.write::<_, _, 4>(1, &prepared_web_rtc_transport_id); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for TupleHash { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for TupleHash { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for TupleHash { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + TupleHash::create( + builder, + &self.local_ice_username_fragment, + &self.web_rtc_transport_id, + ) + } + } + + #[derive(Copy, Clone)] + pub struct TupleHashRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> TupleHashRef<'a> { + pub fn local_ice_username_fragment(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "TupleHash", "local_ice_username_fragment")? + .unwrap_or(0), + ) + } + + pub fn web_rtc_transport_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(1, "TupleHash", "web_rtc_transport_id") + } + } + + impl<'a> ::core::fmt::Debug for TupleHashRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("TupleHashRef"); + f.field( + "local_ice_username_fragment", + &self.local_ice_username_fragment(), + ); + f.field("web_rtc_transport_id", &self.web_rtc_transport_id()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for TupleHash { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: TupleHashRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + local_ice_username_fragment: ::core::convert::TryInto::try_into( + value.local_ice_username_fragment()?, + )?, + web_rtc_transport_id: ::core::convert::TryInto::try_into( + value.web_rtc_transport_id()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for TupleHashRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for TupleHashRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[TupleHashRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for TupleHash { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for TupleHashRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[TupleHashRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct DumpResponse { + pub id: ::planus::alloc::string::String, + pub udp_sockets: ::core::option::Option<::planus::alloc::vec::Vec>, + pub tcp_servers: ::core::option::Option<::planus::alloc::vec::Vec>, + pub web_rtc_transport_ids: ::core::option::Option< + ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + >, + pub local_ice_username_fragments: + ::core::option::Option<::planus::alloc::vec::Vec>, + pub tuple_hashes: + ::core::option::Option<::planus::alloc::vec::Vec>, + } + + impl DumpResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_id: impl ::planus::WriteAs<::planus::Offset>, + field_udp_sockets: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_tcp_servers: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_web_rtc_transport_ids: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_local_ice_username_fragments: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_tuple_hashes: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_id = field_id.prepare(builder); + + let prepared_udp_sockets = field_udp_sockets.prepare(builder); + + let prepared_tcp_servers = field_tcp_servers.prepare(builder); + + let prepared_web_rtc_transport_ids = + field_web_rtc_transport_ids.prepare(builder); + + let prepared_local_ice_username_fragments = + field_local_ice_username_fragments.prepare(builder); + + let prepared_tuple_hashes = field_tuple_hashes.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<14, 24>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_udp_sockets.is_some() { + table_writer + .calculate_size::<::planus::Offset<[::planus::Offset]>>( + 4, + ); + } + if prepared_tcp_servers.is_some() { + table_writer + .calculate_size::<::planus::Offset<[::planus::Offset]>>( + 6, + ); + } + if prepared_web_rtc_transport_ids.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(8); + } + if prepared_local_ice_username_fragments.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(10); + } + if prepared_tuple_hashes.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(12); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_id); + if let ::core::option::Option::Some(prepared_udp_sockets) = + prepared_udp_sockets + { + table_writer.write::<_, _, 4>(1, &prepared_udp_sockets); + } + if let ::core::option::Option::Some(prepared_tcp_servers) = + prepared_tcp_servers + { + table_writer.write::<_, _, 4>(2, &prepared_tcp_servers); + } + if let ::core::option::Option::Some(prepared_web_rtc_transport_ids) = + prepared_web_rtc_transport_ids + { + table_writer.write::<_, _, 4>(3, &prepared_web_rtc_transport_ids); + } + if let ::core::option::Option::Some(prepared_local_ice_username_fragments) = + prepared_local_ice_username_fragments + { + table_writer + .write::<_, _, 4>(4, &prepared_local_ice_username_fragments); + } + if let ::core::option::Option::Some(prepared_tuple_hashes) = + prepared_tuple_hashes + { + table_writer.write::<_, _, 4>(5, &prepared_tuple_hashes); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for DumpResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + DumpResponse::create( + builder, + &self.id, + &self.udp_sockets, + &self.tcp_servers, + &self.web_rtc_transport_ids, + &self.local_ice_username_fragments, + &self.tuple_hashes, + ) + } + } + + #[derive(Copy, Clone)] + pub struct DumpResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DumpResponseRef<'a> { + pub fn id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "DumpResponse", "id") + } + + pub fn udp_sockets( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result>>, + >, + > { + self.0.access(1, "DumpResponse", "udp_sockets") + } + + pub fn tcp_servers( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result>>, + >, + > { + self.0.access(2, "DumpResponse", "tcp_servers") + } + + pub fn web_rtc_transport_ids( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + >, + > { + self.0.access(3, "DumpResponse", "web_rtc_transport_ids") + } + + pub fn local_ice_username_fragments( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result>>, + >, + > { + self.0 + .access(4, "DumpResponse", "local_ice_username_fragments") + } + + pub fn tuple_hashes( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result>>, + >, + > { + self.0.access(5, "DumpResponse", "tuple_hashes") + } + } + + impl<'a> ::core::fmt::Debug for DumpResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DumpResponseRef"); + f.field("id", &self.id()); + if let ::core::option::Option::Some(field_udp_sockets) = + self.udp_sockets().transpose() + { + f.field("udp_sockets", &field_udp_sockets); + } + if let ::core::option::Option::Some(field_tcp_servers) = + self.tcp_servers().transpose() + { + f.field("tcp_servers", &field_tcp_servers); + } + if let ::core::option::Option::Some(field_web_rtc_transport_ids) = + self.web_rtc_transport_ids().transpose() + { + f.field("web_rtc_transport_ids", &field_web_rtc_transport_ids); + } + if let ::core::option::Option::Some(field_local_ice_username_fragments) = + self.local_ice_username_fragments().transpose() + { + f.field( + "local_ice_username_fragments", + &field_local_ice_username_fragments, + ); + } + if let ::core::option::Option::Some(field_tuple_hashes) = + self.tuple_hashes().transpose() + { + f.field("tuple_hashes", &field_tuple_hashes); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for DumpResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DumpResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + id: ::core::convert::TryInto::try_into(value.id()?)?, + udp_sockets: if let ::core::option::Option::Some(udp_sockets) = + value.udp_sockets()? + { + ::core::option::Option::Some(udp_sockets.to_vec_result()?) + } else { + ::core::option::Option::None + }, + tcp_servers: if let ::core::option::Option::Some(tcp_servers) = + value.tcp_servers()? + { + ::core::option::Option::Some(tcp_servers.to_vec_result()?) + } else { + ::core::option::Option::None + }, + web_rtc_transport_ids: if let ::core::option::Option::Some( + web_rtc_transport_ids, + ) = value.web_rtc_transport_ids()? + { + ::core::option::Option::Some(web_rtc_transport_ids.to_vec_result()?) + } else { + ::core::option::Option::None + }, + local_ice_username_fragments: if let ::core::option::Option::Some( + local_ice_username_fragments, + ) = value.local_ice_username_fragments()? + { + ::core::option::Option::Some( + local_ice_username_fragments.to_vec_result()?, + ) + } else { + ::core::option::Option::None + }, + tuple_hashes: if let ::core::option::Option::Some(tuple_hashes) = + value.tuple_hashes()? + { + ::core::option::Option::Some(tuple_hashes.to_vec_result()?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DumpResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DumpResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DumpResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for DumpResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DumpResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[DumpResponseRef]", "read_as_root", 0) + }) + } + } + } + pub mod producer { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct EnableTraceEventRequest { + pub events: ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + } + + impl EnableTraceEventRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_events: impl ::planus::WriteAs<::planus::Offset<[::planus::Offset]>>, + ) -> ::planus::Offset { + let prepared_events = field_events.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_events); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for EnableTraceEventRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for EnableTraceEventRequest + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for EnableTraceEventRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + EnableTraceEventRequest::create(builder, &self.events) + } + } + + #[derive(Copy, Clone)] + pub struct EnableTraceEventRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> EnableTraceEventRequestRef<'a> { + pub fn events( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + > { + self.0 + .access_required(0, "EnableTraceEventRequest", "events") + } + } + + impl<'a> ::core::fmt::Debug for EnableTraceEventRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("EnableTraceEventRequestRef"); + f.field("events", &self.events()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for EnableTraceEventRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: EnableTraceEventRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + events: value.events()?.to_vec_result()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for EnableTraceEventRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for EnableTraceEventRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[EnableTraceEventRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for EnableTraceEventRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for EnableTraceEventRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[EnableTraceEventRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct DumpResponse { + pub id: ::planus::alloc::string::String, + pub kind: super::rtp_parameters::MediaKind, + pub type_: ::planus::alloc::string::String, + pub rtp_parameters: + ::planus::alloc::boxed::Box, + pub rtp_mapping: ::planus::alloc::boxed::Box, + pub rtp_streams: + ::core::option::Option<::planus::alloc::vec::Vec>, + pub trace_event_types: ::planus::alloc::vec::Vec<::planus::alloc::string::String>, + pub paused: bool, + } + + impl DumpResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_id: impl ::planus::WriteAs<::planus::Offset>, + field_kind: impl ::planus::WriteAsDefault< + super::rtp_parameters::MediaKind, + super::rtp_parameters::MediaKind, + >, + field_type_: impl ::planus::WriteAs<::planus::Offset>, + field_rtp_parameters: impl ::planus::WriteAs< + ::planus::Offset, + >, + field_rtp_mapping: impl ::planus::WriteAs< + ::planus::Offset, + >, + field_rtp_streams: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + field_trace_event_types: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_paused: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_id = field_id.prepare(builder); + + let prepared_kind = + field_kind.prepare(builder, &super::rtp_parameters::MediaKind::All); + + let prepared_type_ = field_type_.prepare(builder); + + let prepared_rtp_parameters = field_rtp_parameters.prepare(builder); + + let prepared_rtp_mapping = field_rtp_mapping.prepare(builder); + + let prepared_rtp_streams = field_rtp_streams.prepare(builder); + + let prepared_trace_event_types = field_trace_event_types.prepare(builder); + + let prepared_paused = field_paused.prepare(builder, &false); + + let mut table_writer = + ::planus::table_writer::TableWriter::<18, 26>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_kind.is_some() { + table_writer.calculate_size::(4); + } + table_writer.calculate_size::<::planus::Offset>(6); + table_writer + .calculate_size::<::planus::Offset>( + 8, + ); + table_writer + .calculate_size::<::planus::Offset>(10); + if prepared_rtp_streams.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(12); + } + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(14); + if prepared_paused.is_some() { + table_writer.calculate_size::(16); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_id); + table_writer.write::<_, _, 4>(2, &prepared_type_); + table_writer.write::<_, _, 4>(3, &prepared_rtp_parameters); + table_writer.write::<_, _, 4>(4, &prepared_rtp_mapping); + if let ::core::option::Option::Some(prepared_rtp_streams) = + prepared_rtp_streams + { + table_writer.write::<_, _, 4>(5, &prepared_rtp_streams); + } + table_writer.write::<_, _, 4>(6, &prepared_trace_event_types); + if let ::core::option::Option::Some(prepared_kind) = prepared_kind { + table_writer.write::<_, _, 1>(1, &prepared_kind); + } + if let ::core::option::Option::Some(prepared_paused) = prepared_paused { + table_writer.write::<_, _, 1>(7, &prepared_paused); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for DumpResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + DumpResponse::create( + builder, + &self.id, + &self.kind, + &self.type_, + &self.rtp_parameters, + &self.rtp_mapping, + &self.rtp_streams, + &self.trace_event_types, + &self.paused, + ) + } + } + + #[derive(Copy, Clone)] + pub struct DumpResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DumpResponseRef<'a> { + pub fn id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "DumpResponse", "id") + } + + pub fn kind(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "DumpResponse", "kind")? + .unwrap_or(super::rtp_parameters::MediaKind::All), + ) + } + + pub fn type_(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(2, "DumpResponse", "type_") + } + + pub fn rtp_parameters( + &self, + ) -> ::planus::Result> { + self.0.access_required(3, "DumpResponse", "rtp_parameters") + } + + pub fn rtp_mapping( + &self, + ) -> ::planus::Result> { + self.0.access_required(4, "DumpResponse", "rtp_mapping") + } + + pub fn rtp_streams( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result>>, + >, + > { + self.0.access(5, "DumpResponse", "rtp_streams") + } + + pub fn trace_event_types( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result<&'a ::core::primitive::str>>, + > { + self.0 + .access_required(6, "DumpResponse", "trace_event_types") + } + + pub fn paused(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(7, "DumpResponse", "paused")?.unwrap_or(false), + ) + } + } + + impl<'a> ::core::fmt::Debug for DumpResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DumpResponseRef"); + f.field("id", &self.id()); + f.field("kind", &self.kind()); + f.field("type_", &self.type_()); + f.field("rtp_parameters", &self.rtp_parameters()); + f.field("rtp_mapping", &self.rtp_mapping()); + if let ::core::option::Option::Some(field_rtp_streams) = + self.rtp_streams().transpose() + { + f.field("rtp_streams", &field_rtp_streams); + } + f.field("trace_event_types", &self.trace_event_types()); + f.field("paused", &self.paused()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for DumpResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DumpResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + id: ::core::convert::TryInto::try_into(value.id()?)?, + kind: ::core::convert::TryInto::try_into(value.kind()?)?, + type_: ::core::convert::TryInto::try_into(value.type_()?)?, + rtp_parameters: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.rtp_parameters()?)?, + ), + rtp_mapping: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.rtp_mapping()?)?, + ), + rtp_streams: if let ::core::option::Option::Some(rtp_streams) = + value.rtp_streams()? + { + ::core::option::Option::Some(rtp_streams.to_vec_result()?) + } else { + ::core::option::Option::None + }, + trace_event_types: value.trace_event_types()?.to_vec_result()?, + paused: ::core::convert::TryInto::try_into(value.paused()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DumpResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DumpResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DumpResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for DumpResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DumpResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[DumpResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, Debug, PartialEq, PartialOrd, ::serde::Serialize, ::serde::Deserialize, + )] + pub struct GetStatsResponse { + pub stats: + ::core::option::Option<::planus::alloc::vec::Vec>, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for GetStatsResponse { + fn default() -> Self { + Self { + stats: ::core::default::Default::default(), + } + } + } + + impl GetStatsResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_stats: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_stats = field_stats.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_stats.is_some() { + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_stats) = prepared_stats { + table_writer.write::<_, _, 4>(0, &prepared_stats); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for GetStatsResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + GetStatsResponse::create(builder, &self.stats) + } + } + + #[derive(Copy, Clone)] + pub struct GetStatsResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> GetStatsResponseRef<'a> { + pub fn stats( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result>>, + >, + > { + self.0.access(0, "GetStatsResponse", "stats") + } + } + + impl<'a> ::core::fmt::Debug for GetStatsResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("GetStatsResponseRef"); + if let ::core::option::Option::Some(field_stats) = self.stats().transpose() { + f.field("stats", &field_stats); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for GetStatsResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: GetStatsResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + stats: if let ::core::option::Option::Some(stats) = value.stats()? { + ::core::option::Option::Some(stats.to_vec_result()?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for GetStatsResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for GetStatsResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[GetStatsResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for GetStatsResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for GetStatsResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[GetStatsResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct SendNotification { + pub data: ::planus::alloc::vec::Vec, + } + + impl SendNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_data: impl ::planus::WriteAs<::planus::Offset<[u8]>>, + ) -> ::planus::Offset { + let prepared_data = field_data.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset<[u8]>>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_data); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for SendNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for SendNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for SendNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + SendNotification::create(builder, &self.data) + } + } + + #[derive(Copy, Clone)] + pub struct SendNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> SendNotificationRef<'a> { + pub fn data(&self) -> ::planus::Result<::planus::Vector<'a, u8>> { + self.0.access_required(0, "SendNotification", "data") + } + } + + impl<'a> ::core::fmt::Debug for SendNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("SendNotificationRef"); + f.field("data", &self.data()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for SendNotification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: SendNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + data: value.data()?.to_vec()?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for SendNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for SendNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[SendNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for SendNotification { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for SendNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[SendNotificationRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Score { + pub ssrc: u32, + pub rid: ::core::option::Option<::planus::alloc::string::String>, + pub score: u8, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for Score { + fn default() -> Self { + Self { + ssrc: 0, + rid: ::core::default::Default::default(), + score: 0, + } + } + } + + impl Score { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ssrc: impl ::planus::WriteAsDefault, + field_rid: impl ::planus::WriteAsOptional<::planus::Offset<::core::primitive::str>>, + field_score: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_ssrc = field_ssrc.prepare(builder, &0); + + let prepared_rid = field_rid.prepare(builder); + + let prepared_score = field_score.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<8, 9>::new(builder); + + if prepared_ssrc.is_some() { + table_writer.calculate_size::(2); + } + if prepared_rid.is_some() { + table_writer.calculate_size::<::planus::Offset>(4); + } + if prepared_score.is_some() { + table_writer.calculate_size::(6); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_ssrc) = prepared_ssrc { + table_writer.write::<_, _, 4>(0, &prepared_ssrc); + } + if let ::core::option::Option::Some(prepared_rid) = prepared_rid { + table_writer.write::<_, _, 4>(1, &prepared_rid); + } + if let ::core::option::Option::Some(prepared_score) = prepared_score { + table_writer.write::<_, _, 1>(2, &prepared_score); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Score { + type Prepared = ::planus::Offset; + + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Score { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Score { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset { + Score::create(builder, &self.ssrc, &self.rid, &self.score) + } + } + + #[derive(Copy, Clone)] + pub struct ScoreRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ScoreRef<'a> { + pub fn ssrc(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(0, "Score", "ssrc")?.unwrap_or(0)) + } + + pub fn rid( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(1, "Score", "rid") + } + + pub fn score(&self) -> ::planus::Result { + ::core::result::Result::Ok(self.0.access(2, "Score", "score")?.unwrap_or(0)) + } + } + + impl<'a> ::core::fmt::Debug for ScoreRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ScoreRef"); + f.field("ssrc", &self.ssrc()); + if let ::core::option::Option::Some(field_rid) = self.rid().transpose() { + f.field("rid", &field_rid); + } + f.field("score", &self.score()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Score { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ScoreRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ssrc: ::core::convert::TryInto::try_into(value.ssrc()?)?, + rid: if let ::core::option::Option::Some(rid) = value.rid()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(rid)?) + } else { + ::core::option::Option::None + }, + score: ::core::convert::TryInto::try_into(value.score()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ScoreRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ScoreRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ScoreRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Score { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ScoreRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ScoreRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ScoreNotification { + pub scores: ::core::option::Option<::planus::alloc::vec::Vec>, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for ScoreNotification { + fn default() -> Self { + Self { + scores: ::core::default::Default::default(), + } + } + } + + impl ScoreNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_scores: impl ::planus::WriteAsOptional< + ::planus::Offset<[::planus::Offset]>, + >, + ) -> ::planus::Offset { + let prepared_scores = field_scores.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_scores.is_some() { + table_writer + .calculate_size::<::planus::Offset<[::planus::Offset]>>(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_scores) = prepared_scores { + table_writer.write::<_, _, 4>(0, &prepared_scores); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ScoreNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ScoreNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ScoreNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ScoreNotification::create(builder, &self.scores) + } + } + + #[derive(Copy, Clone)] + pub struct ScoreNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ScoreNotificationRef<'a> { + pub fn scores( + &self, + ) -> ::planus::Result< + ::core::option::Option< + ::planus::Vector<'a, ::planus::Result>>, + >, + > { + self.0.access(0, "ScoreNotification", "scores") + } + } + + impl<'a> ::core::fmt::Debug for ScoreNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ScoreNotificationRef"); + if let ::core::option::Option::Some(field_scores) = self.scores().transpose() { + f.field("scores", &field_scores); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ScoreNotification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ScoreNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + scores: if let ::core::option::Option::Some(scores) = value.scores()? { + ::core::option::Option::Some(scores.to_vec_result()?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ScoreNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ScoreNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ScoreNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ScoreNotification { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ScoreNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ScoreNotificationRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct VideoOrientationChangeNotification { + pub camera: bool, + pub flip: bool, + pub rotation: u16, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for VideoOrientationChangeNotification { + fn default() -> Self { + Self { + camera: false, + flip: false, + rotation: 0, + } + } + } + + impl VideoOrientationChangeNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_camera: impl ::planus::WriteAsDefault, + field_flip: impl ::planus::WriteAsDefault, + field_rotation: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_camera = field_camera.prepare(builder, &false); + + let prepared_flip = field_flip.prepare(builder, &false); + + let prepared_rotation = field_rotation.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<8, 4>::new(builder); + + if prepared_camera.is_some() { + table_writer.calculate_size::(2); + } + if prepared_flip.is_some() { + table_writer.calculate_size::(4); + } + if prepared_rotation.is_some() { + table_writer.calculate_size::(6); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_rotation) = prepared_rotation { + table_writer.write::<_, _, 2>(2, &prepared_rotation); + } + if let ::core::option::Option::Some(prepared_camera) = prepared_camera { + table_writer.write::<_, _, 1>(0, &prepared_camera); + } + if let ::core::option::Option::Some(prepared_flip) = prepared_flip { + table_writer.write::<_, _, 1>(1, &prepared_flip); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for VideoOrientationChangeNotification + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for VideoOrientationChangeNotification + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset + for VideoOrientationChangeNotification + { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + VideoOrientationChangeNotification::create( + builder, + &self.camera, + &self.flip, + &self.rotation, + ) + } + } + + #[derive(Copy, Clone)] + pub struct VideoOrientationChangeNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> VideoOrientationChangeNotificationRef<'a> { + pub fn camera(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "VideoOrientationChangeNotification", "camera")? + .unwrap_or(false), + ) + } + + pub fn flip(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "VideoOrientationChangeNotification", "flip")? + .unwrap_or(false), + ) + } + + pub fn rotation(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "VideoOrientationChangeNotification", "rotation")? + .unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for VideoOrientationChangeNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("VideoOrientationChangeNotificationRef"); + f.field("camera", &self.camera()); + f.field("flip", &self.flip()); + f.field("rotation", &self.rotation()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for VideoOrientationChangeNotification + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from( + value: VideoOrientationChangeNotificationRef<'a>, + ) -> ::planus::Result { + ::core::result::Result::Ok(Self { + camera: ::core::convert::TryInto::try_into(value.camera()?)?, + flip: ::core::convert::TryInto::try_into(value.flip()?)?, + rotation: ::core::convert::TryInto::try_into(value.rotation()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for VideoOrientationChangeNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for VideoOrientationChangeNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[VideoOrientationChangeNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for VideoOrientationChangeNotification + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for VideoOrientationChangeNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[VideoOrientationChangeNotificationRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum TraceType { + Keyframe = 0, + Fir = 1, + Nack = 2, + Pli = 3, + Rtp = 4, + } + + impl ::core::convert::TryFrom for TraceType { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 0 => ::core::result::Result::Ok(TraceType::Keyframe), + 1 => ::core::result::Result::Ok(TraceType::Fir), + 2 => ::core::result::Result::Ok(TraceType::Nack), + 3 => ::core::result::Result::Ok(TraceType::Pli), + 4 => ::core::result::Result::Ok(TraceType::Rtp), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: TraceType) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for TraceType { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for TraceType { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for TraceType { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> TraceType { + *self + } + } + + impl ::planus::WriteAsDefault for TraceType { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &TraceType, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for TraceType { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for TraceType { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for TraceType { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "TraceType", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for TraceType { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum TraceDirection { + DirectionIn = 0, + DirectionOut = 1, + } + + impl ::core::convert::TryFrom for TraceDirection { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 0 => ::core::result::Result::Ok(TraceDirection::DirectionIn), + 1 => ::core::result::Result::Ok(TraceDirection::DirectionOut), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: TraceDirection) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for TraceDirection { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for TraceDirection { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for TraceDirection { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> TraceDirection { + *self + } + } + + impl ::planus::WriteAsDefault for TraceDirection { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &TraceDirection, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for TraceDirection { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for TraceDirection { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for TraceDirection { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "TraceDirection", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for TraceDirection { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub enum TraceInfo { + KeyFrameTraceInfo(::planus::alloc::boxed::Box), + FirTraceInfo(::planus::alloc::boxed::Box), + PliTraceInfo(::planus::alloc::boxed::Box), + RtpTraceInfo(::planus::alloc::boxed::Box), + } + + impl TraceInfo { + pub fn create_key_frame_trace_info( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(1, value.prepare(builder).downcast()) + } + + pub fn create_fir_trace_info( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(2, value.prepare(builder).downcast()) + } + + pub fn create_pli_trace_info( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(3, value.prepare(builder).downcast()) + } + + pub fn create_rtp_trace_info( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(4, value.prepare(builder).downcast()) + } + } + + impl ::planus::WriteAsUnion for TraceInfo { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::UnionOffset { + match self { + Self::KeyFrameTraceInfo(value) => { + Self::create_key_frame_trace_info(builder, value) + } + Self::FirTraceInfo(value) => Self::create_fir_trace_info(builder, value), + Self::PliTraceInfo(value) => Self::create_pli_trace_info(builder, value), + Self::RtpTraceInfo(value) => Self::create_rtp_trace_info(builder, value), + } + } + } + + impl ::planus::WriteAsOptionalUnion for TraceInfo { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::UnionOffset> { + ::core::option::Option::Some(::planus::WriteAsUnion::prepare(self, builder)) + } + } + + #[derive(Copy, Clone, Debug)] + pub enum TraceInfoRef<'a> { + KeyFrameTraceInfo(self::KeyFrameTraceInfoRef<'a>), + FirTraceInfo(self::FirTraceInfoRef<'a>), + PliTraceInfo(self::PliTraceInfoRef<'a>), + RtpTraceInfo(self::RtpTraceInfoRef<'a>), + } + + impl<'a> ::core::convert::TryFrom> for TraceInfo { + type Error = ::planus::Error; + + fn try_from(value: TraceInfoRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(match value { + TraceInfoRef::KeyFrameTraceInfo(value) => { + TraceInfo::KeyFrameTraceInfo(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + TraceInfoRef::FirTraceInfo(value) => { + TraceInfo::FirTraceInfo(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + TraceInfoRef::PliTraceInfo(value) => { + TraceInfo::PliTraceInfo(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + TraceInfoRef::RtpTraceInfo(value) => { + TraceInfo::RtpTraceInfo(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + }) + } + } + + impl<'a> ::planus::TableReadUnion<'a> for TraceInfoRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + field_offset: usize, + tag: u8, + ) -> ::core::result::Result { + match tag { + 1 => ::core::result::Result::Ok(Self::KeyFrameTraceInfo( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 2 => ::core::result::Result::Ok(Self::FirTraceInfo( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 3 => ::core::result::Result::Ok(Self::PliTraceInfo( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 4 => ::core::result::Result::Ok(Self::RtpTraceInfo( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + _ => ::core::result::Result::Err( + ::planus::errors::ErrorKind::UnknownUnionTag { tag }, + ), + } + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct KeyFrameTraceInfo { + pub is_rtx: bool, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for KeyFrameTraceInfo { + fn default() -> Self { + Self { is_rtx: false } + } + } + + impl KeyFrameTraceInfo { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_is_rtx: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_is_rtx = field_is_rtx.prepare(builder, &false); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 1>::new(builder); + + if prepared_is_rtx.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_is_rtx) = prepared_is_rtx { + table_writer.write::<_, _, 1>(0, &prepared_is_rtx); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for KeyFrameTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for KeyFrameTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for KeyFrameTraceInfo { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + KeyFrameTraceInfo::create(builder, &self.is_rtx) + } + } + + #[derive(Copy, Clone)] + pub struct KeyFrameTraceInfoRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> KeyFrameTraceInfoRef<'a> { + pub fn is_rtx(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "KeyFrameTraceInfo", "is_rtx")? + .unwrap_or(false), + ) + } + } + + impl<'a> ::core::fmt::Debug for KeyFrameTraceInfoRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("KeyFrameTraceInfoRef"); + f.field("is_rtx", &self.is_rtx()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for KeyFrameTraceInfo { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: KeyFrameTraceInfoRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + is_rtx: ::core::convert::TryInto::try_into(value.is_rtx()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for KeyFrameTraceInfoRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for KeyFrameTraceInfoRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[KeyFrameTraceInfoRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for KeyFrameTraceInfo { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for KeyFrameTraceInfoRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[KeyFrameTraceInfoRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct FirTraceInfo { + pub ssrc: u32, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for FirTraceInfo { + fn default() -> Self { + Self { ssrc: 0 } + } + } + + impl FirTraceInfo { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ssrc: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_ssrc = field_ssrc.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_ssrc.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_ssrc) = prepared_ssrc { + table_writer.write::<_, _, 4>(0, &prepared_ssrc); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for FirTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for FirTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for FirTraceInfo { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + FirTraceInfo::create(builder, &self.ssrc) + } + } + + #[derive(Copy, Clone)] + pub struct FirTraceInfoRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> FirTraceInfoRef<'a> { + pub fn ssrc(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "FirTraceInfo", "ssrc")?.unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for FirTraceInfoRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("FirTraceInfoRef"); + f.field("ssrc", &self.ssrc()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for FirTraceInfo { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: FirTraceInfoRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ssrc: ::core::convert::TryInto::try_into(value.ssrc()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for FirTraceInfoRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for FirTraceInfoRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[FirTraceInfoRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for FirTraceInfo { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for FirTraceInfoRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[FirTraceInfoRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct PliTraceInfo { + pub ssrc: u32, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for PliTraceInfo { + fn default() -> Self { + Self { ssrc: 0 } + } + } + + impl PliTraceInfo { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ssrc: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_ssrc = field_ssrc.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_ssrc.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_ssrc) = prepared_ssrc { + table_writer.write::<_, _, 4>(0, &prepared_ssrc); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for PliTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for PliTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for PliTraceInfo { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + PliTraceInfo::create(builder, &self.ssrc) + } + } + + #[derive(Copy, Clone)] + pub struct PliTraceInfoRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> PliTraceInfoRef<'a> { + pub fn ssrc(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "PliTraceInfo", "ssrc")?.unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for PliTraceInfoRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("PliTraceInfoRef"); + f.field("ssrc", &self.ssrc()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for PliTraceInfo { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: PliTraceInfoRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ssrc: ::core::convert::TryInto::try_into(value.ssrc()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for PliTraceInfoRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for PliTraceInfoRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[PliTraceInfoRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for PliTraceInfo { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for PliTraceInfoRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[PliTraceInfoRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct RtpTraceInfo { + pub is_rtx: bool, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for RtpTraceInfo { + fn default() -> Self { + Self { is_rtx: false } + } + } + + impl RtpTraceInfo { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_is_rtx: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_is_rtx = field_is_rtx.prepare(builder, &false); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 1>::new(builder); + + if prepared_is_rtx.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_is_rtx) = prepared_is_rtx { + table_writer.write::<_, _, 1>(0, &prepared_is_rtx); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RtpTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RtpTraceInfo { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RtpTraceInfo { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + RtpTraceInfo::create(builder, &self.is_rtx) + } + } + + #[derive(Copy, Clone)] + pub struct RtpTraceInfoRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RtpTraceInfoRef<'a> { + pub fn is_rtx(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(0, "RtpTraceInfo", "is_rtx")?.unwrap_or(false), + ) + } + } + + impl<'a> ::core::fmt::Debug for RtpTraceInfoRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RtpTraceInfoRef"); + f.field("is_rtx", &self.is_rtx()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RtpTraceInfo { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RtpTraceInfoRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + is_rtx: ::core::convert::TryInto::try_into(value.is_rtx()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RtpTraceInfoRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RtpTraceInfoRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RtpTraceInfoRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RtpTraceInfo { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RtpTraceInfoRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[RtpTraceInfoRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct TraceNotification { + pub type_: self::TraceType, + pub timestamp: u64, + pub direction: self::TraceDirection, + pub info: ::core::option::Option, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for TraceNotification { + fn default() -> Self { + Self { + type_: self::TraceType::Keyframe, + timestamp: 0, + direction: self::TraceDirection::DirectionIn, + info: ::core::default::Default::default(), + } + } + } + + impl TraceNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_type_: impl ::planus::WriteAsDefault, + field_timestamp: impl ::planus::WriteAsDefault, + field_direction: impl ::planus::WriteAsDefault< + self::TraceDirection, + self::TraceDirection, + >, + field_info: impl ::planus::WriteAsOptionalUnion, + ) -> ::planus::Offset { + let prepared_type_ = field_type_.prepare(builder, &self::TraceType::Keyframe); + + let prepared_timestamp = field_timestamp.prepare(builder, &0); + + let prepared_direction = + field_direction.prepare(builder, &self::TraceDirection::DirectionIn); + + let prepared_info = field_info.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<10, 15>::new(builder); + + if prepared_type_.is_some() { + table_writer.calculate_size::(2); + } + if prepared_timestamp.is_some() { + table_writer.calculate_size::(4); + } + if prepared_direction.is_some() { + table_writer.calculate_size::(6); + } + if prepared_info.is_some() { + table_writer.calculate_size::(8); + table_writer.calculate_size::<::planus::Offset>(10); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_timestamp) = prepared_timestamp + { + table_writer.write::<_, _, 8>(1, &prepared_timestamp); + } + if let ::core::option::Option::Some(prepared_info) = prepared_info { + table_writer.write::<_, _, 4>(4, &prepared_info.offset()); + } + if let ::core::option::Option::Some(prepared_type_) = prepared_type_ { + table_writer.write::<_, _, 1>(0, &prepared_type_); + } + if let ::core::option::Option::Some(prepared_direction) = prepared_direction + { + table_writer.write::<_, _, 1>(2, &prepared_direction); + } + if let ::core::option::Option::Some(prepared_info) = prepared_info { + table_writer.write::<_, _, 1>(3, &prepared_info.tag()); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for TraceNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for TraceNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for TraceNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + TraceNotification::create( + builder, + &self.type_, + &self.timestamp, + &self.direction, + &self.info, + ) + } + } + + #[derive(Copy, Clone)] + pub struct TraceNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> TraceNotificationRef<'a> { + pub fn type_(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "TraceNotification", "type_")? + .unwrap_or(self::TraceType::Keyframe), + ) + } + + pub fn timestamp(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "TraceNotification", "timestamp")? + .unwrap_or(0), + ) + } + + pub fn direction(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "TraceNotification", "direction")? + .unwrap_or(self::TraceDirection::DirectionIn), + ) + } + + pub fn info( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access_union(3, "TraceNotification", "info") + } + } + + impl<'a> ::core::fmt::Debug for TraceNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("TraceNotificationRef"); + f.field("type_", &self.type_()); + f.field("timestamp", &self.timestamp()); + f.field("direction", &self.direction()); + if let ::core::option::Option::Some(field_info) = self.info().transpose() { + f.field("info", &field_info); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for TraceNotification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: TraceNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + type_: ::core::convert::TryInto::try_into(value.type_()?)?, + timestamp: ::core::convert::TryInto::try_into(value.timestamp()?)?, + direction: ::core::convert::TryInto::try_into(value.direction()?)?, + info: if let ::core::option::Option::Some(info) = value.info()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(info)?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for TraceNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for TraceNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[TraceNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for TraceNotification { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for TraceNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[TraceNotificationRef]", "read_as_root", 0) + }) + } + } + } + pub mod pipe_transport { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct PipeTransportOptions { + pub base: ::planus::alloc::boxed::Box, + pub listen_ip: ::planus::alloc::boxed::Box, + pub port: u16, + pub enable_rtx: bool, + pub enable_srtp: bool, + } + + impl PipeTransportOptions { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + field_listen_ip: impl ::planus::WriteAs< + ::planus::Offset, + >, + field_port: impl ::planus::WriteAsDefault, + field_enable_rtx: impl ::planus::WriteAsDefault, + field_enable_srtp: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let prepared_listen_ip = field_listen_ip.prepare(builder); + + let prepared_port = field_port.prepare(builder, &0); + + let prepared_enable_rtx = field_enable_rtx.prepare(builder, &false); + + let prepared_enable_srtp = field_enable_srtp.prepare(builder, &false); + + let mut table_writer = + ::planus::table_writer::TableWriter::<12, 12>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + if prepared_port.is_some() { + table_writer.calculate_size::(6); + } + if prepared_enable_rtx.is_some() { + table_writer.calculate_size::(8); + } + if prepared_enable_srtp.is_some() { + table_writer.calculate_size::(10); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_base); + table_writer.write::<_, _, 4>(1, &prepared_listen_ip); + if let ::core::option::Option::Some(prepared_port) = prepared_port { + table_writer.write::<_, _, 2>(2, &prepared_port); + } + if let ::core::option::Option::Some(prepared_enable_rtx) = + prepared_enable_rtx + { + table_writer.write::<_, _, 1>(3, &prepared_enable_rtx); + } + if let ::core::option::Option::Some(prepared_enable_srtp) = + prepared_enable_srtp + { + table_writer.write::<_, _, 1>(4, &prepared_enable_srtp); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for PipeTransportOptions { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for PipeTransportOptions { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for PipeTransportOptions { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + PipeTransportOptions::create( + builder, + &self.base, + &self.listen_ip, + &self.port, + &self.enable_rtx, + &self.enable_srtp, + ) + } + } + + #[derive(Copy, Clone)] + pub struct PipeTransportOptionsRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> PipeTransportOptionsRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "PipeTransportOptions", "base") + } + + pub fn listen_ip(&self) -> ::planus::Result> { + self.0 + .access_required(1, "PipeTransportOptions", "listen_ip") + } + + pub fn port(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "PipeTransportOptions", "port")? + .unwrap_or(0), + ) + } + + pub fn enable_rtx(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(3, "PipeTransportOptions", "enable_rtx")? + .unwrap_or(false), + ) + } + + pub fn enable_srtp(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(4, "PipeTransportOptions", "enable_srtp")? + .unwrap_or(false), + ) + } + } + + impl<'a> ::core::fmt::Debug for PipeTransportOptionsRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("PipeTransportOptionsRef"); + f.field("base", &self.base()); + f.field("listen_ip", &self.listen_ip()); + f.field("port", &self.port()); + f.field("enable_rtx", &self.enable_rtx()); + f.field("enable_srtp", &self.enable_srtp()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for PipeTransportOptions { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: PipeTransportOptionsRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + listen_ip: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.listen_ip()?)?, + ), + port: ::core::convert::TryInto::try_into(value.port()?)?, + enable_rtx: ::core::convert::TryInto::try_into(value.enable_rtx()?)?, + enable_srtp: ::core::convert::TryInto::try_into(value.enable_srtp()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for PipeTransportOptionsRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for PipeTransportOptionsRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[PipeTransportOptionsRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for PipeTransportOptions { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for PipeTransportOptionsRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[PipeTransportOptionsRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ConnectRequest { + pub ip: ::planus::alloc::string::String, + pub port: ::core::option::Option, + pub srtp_parameters: ::core::option::Option< + ::planus::alloc::boxed::Box, + >, + } + + impl ConnectRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ip: impl ::planus::WriteAs<::planus::Offset>, + field_port: impl ::planus::WriteAsOptional, + field_srtp_parameters: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_ip = field_ip.prepare(builder); + + let prepared_port = field_port.prepare(builder); + + let prepared_srtp_parameters = field_srtp_parameters.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<8, 10>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_port.is_some() { + table_writer.calculate_size::(4); + } + if prepared_srtp_parameters.is_some() { + table_writer + .calculate_size::<::planus::Offset>( + 6, + ); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_ip); + if let ::core::option::Option::Some(prepared_srtp_parameters) = + prepared_srtp_parameters + { + table_writer.write::<_, _, 4>(2, &prepared_srtp_parameters); + } + if let ::core::option::Option::Some(prepared_port) = prepared_port { + table_writer.write::<_, _, 2>(1, &prepared_port); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ConnectRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ConnectRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ConnectRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ConnectRequest::create(builder, &self.ip, &self.port, &self.srtp_parameters) + } + } + + #[derive(Copy, Clone)] + pub struct ConnectRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ConnectRequestRef<'a> { + pub fn ip(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "ConnectRequest", "ip") + } + + pub fn port(&self) -> ::planus::Result<::core::option::Option> { + self.0.access(1, "ConnectRequest", "port") + } + + pub fn srtp_parameters( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(2, "ConnectRequest", "srtp_parameters") + } + } + + impl<'a> ::core::fmt::Debug for ConnectRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ConnectRequestRef"); + f.field("ip", &self.ip()); + if let ::core::option::Option::Some(field_port) = self.port().transpose() { + f.field("port", &field_port); + } + if let ::core::option::Option::Some(field_srtp_parameters) = + self.srtp_parameters().transpose() + { + f.field("srtp_parameters", &field_srtp_parameters); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ConnectRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ConnectRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ip: ::core::convert::TryInto::try_into(value.ip()?)?, + port: if let ::core::option::Option::Some(port) = value.port()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(port)?) + } else { + ::core::option::Option::None + }, + srtp_parameters: if let ::core::option::Option::Some(srtp_parameters) = + value.srtp_parameters()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(srtp_parameters)?, + )) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ConnectRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ConnectRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ConnectRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ConnectRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ConnectRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ConnectRequestRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ConnectResponse { + pub tuple: + ::core::option::Option<::planus::alloc::boxed::Box>, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for ConnectResponse { + fn default() -> Self { + Self { + tuple: ::core::default::Default::default(), + } + } + } + + impl ConnectResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_tuple: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_tuple = field_tuple.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + if prepared_tuple.is_some() { + table_writer.calculate_size::<::planus::Offset>(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_tuple) = prepared_tuple { + table_writer.write::<_, _, 4>(0, &prepared_tuple); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ConnectResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ConnectResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ConnectResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ConnectResponse::create(builder, &self.tuple) + } + } + + #[derive(Copy, Clone)] + pub struct ConnectResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ConnectResponseRef<'a> { + pub fn tuple( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(0, "ConnectResponse", "tuple") + } + } + + impl<'a> ::core::fmt::Debug for ConnectResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ConnectResponseRef"); + if let ::core::option::Option::Some(field_tuple) = self.tuple().transpose() { + f.field("tuple", &field_tuple); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ConnectResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ConnectResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + tuple: if let ::core::option::Option::Some(tuple) = value.tuple()? { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(tuple)?, + )) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ConnectResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ConnectResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ConnectResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ConnectResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ConnectResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ConnectResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct DumpResponse { + pub base: ::planus::alloc::boxed::Box, + pub tuple: ::planus::alloc::boxed::Box, + pub rtx: bool, + pub srtp_parameters: ::core::option::Option< + ::planus::alloc::boxed::Box, + >, + } + + impl DumpResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + field_tuple: impl ::planus::WriteAs<::planus::Offset>, + field_rtx: impl ::planus::WriteAsDefault, + field_srtp_parameters: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let prepared_tuple = field_tuple.prepare(builder); + + let prepared_rtx = field_rtx.prepare(builder, &false); + + let prepared_srtp_parameters = field_srtp_parameters.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<10, 13>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + if prepared_rtx.is_some() { + table_writer.calculate_size::(6); + } + if prepared_srtp_parameters.is_some() { + table_writer + .calculate_size::<::planus::Offset>( + 8, + ); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_base); + table_writer.write::<_, _, 4>(1, &prepared_tuple); + if let ::core::option::Option::Some(prepared_srtp_parameters) = + prepared_srtp_parameters + { + table_writer.write::<_, _, 4>(3, &prepared_srtp_parameters); + } + if let ::core::option::Option::Some(prepared_rtx) = prepared_rtx { + table_writer.write::<_, _, 1>(2, &prepared_rtx); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for DumpResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + DumpResponse::create( + builder, + &self.base, + &self.tuple, + &self.rtx, + &self.srtp_parameters, + ) + } + } + + #[derive(Copy, Clone)] + pub struct DumpResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DumpResponseRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "DumpResponse", "base") + } + + pub fn tuple(&self) -> ::planus::Result> { + self.0.access_required(1, "DumpResponse", "tuple") + } + + pub fn rtx(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(2, "DumpResponse", "rtx")?.unwrap_or(false), + ) + } + + pub fn srtp_parameters( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(3, "DumpResponse", "srtp_parameters") + } + } + + impl<'a> ::core::fmt::Debug for DumpResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DumpResponseRef"); + f.field("base", &self.base()); + f.field("tuple", &self.tuple()); + f.field("rtx", &self.rtx()); + if let ::core::option::Option::Some(field_srtp_parameters) = + self.srtp_parameters().transpose() + { + f.field("srtp_parameters", &field_srtp_parameters); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for DumpResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DumpResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + tuple: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.tuple()?)?, + ), + rtx: ::core::convert::TryInto::try_into(value.rtx()?)?, + srtp_parameters: if let ::core::option::Option::Some(srtp_parameters) = + value.srtp_parameters()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(srtp_parameters)?, + )) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DumpResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DumpResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DumpResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for DumpResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DumpResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[DumpResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct GetStatsResponse { + pub base: ::planus::alloc::boxed::Box, + pub tuple: ::planus::alloc::boxed::Box, + } + + impl GetStatsResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + field_tuple: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let prepared_tuple = field_tuple.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_base); + table_writer.write::<_, _, 4>(1, &prepared_tuple); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for GetStatsResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + GetStatsResponse::create(builder, &self.base, &self.tuple) + } + } + + #[derive(Copy, Clone)] + pub struct GetStatsResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> GetStatsResponseRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "GetStatsResponse", "base") + } + + pub fn tuple(&self) -> ::planus::Result> { + self.0.access_required(1, "GetStatsResponse", "tuple") + } + } + + impl<'a> ::core::fmt::Debug for GetStatsResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("GetStatsResponseRef"); + f.field("base", &self.base()); + f.field("tuple", &self.tuple()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for GetStatsResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: GetStatsResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + tuple: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.tuple()?)?, + ), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for GetStatsResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for GetStatsResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[GetStatsResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for GetStatsResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for GetStatsResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[GetStatsResponseRef]", "read_as_root", 0) + }) + } + } + } + pub mod plain_transport { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct PlainTransportOptions { + pub base: + ::core::option::Option<::planus::alloc::boxed::Box>, + pub listen_ip: ::planus::alloc::boxed::Box, + pub port: u16, + pub rtcp_mux: bool, + pub comedia: bool, + pub enable_srtp: bool, + pub srtp_crypto_suite: ::core::option::Option<::planus::alloc::string::String>, + } + + impl PlainTransportOptions { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + field_listen_ip: impl ::planus::WriteAs< + ::planus::Offset, + >, + field_port: impl ::planus::WriteAsDefault, + field_rtcp_mux: impl ::planus::WriteAsDefault, + field_comedia: impl ::planus::WriteAsDefault, + field_enable_srtp: impl ::planus::WriteAsDefault, + field_srtp_crypto_suite: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let prepared_listen_ip = field_listen_ip.prepare(builder); + + let prepared_port = field_port.prepare(builder, &0); + + let prepared_rtcp_mux = field_rtcp_mux.prepare(builder, &false); + + let prepared_comedia = field_comedia.prepare(builder, &false); + + let prepared_enable_srtp = field_enable_srtp.prepare(builder, &false); + + let prepared_srtp_crypto_suite = field_srtp_crypto_suite.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<16, 17>::new(builder); + + if prepared_base.is_some() { + table_writer + .calculate_size::<::planus::Offset>(2); + } + table_writer.calculate_size::<::planus::Offset>(4); + if prepared_port.is_some() { + table_writer.calculate_size::(6); + } + if prepared_rtcp_mux.is_some() { + table_writer.calculate_size::(8); + } + if prepared_comedia.is_some() { + table_writer.calculate_size::(10); + } + if prepared_enable_srtp.is_some() { + table_writer.calculate_size::(12); + } + if prepared_srtp_crypto_suite.is_some() { + table_writer.calculate_size::<::planus::Offset>(14); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_base) = prepared_base { + table_writer.write::<_, _, 4>(0, &prepared_base); + } + table_writer.write::<_, _, 4>(1, &prepared_listen_ip); + if let ::core::option::Option::Some(prepared_srtp_crypto_suite) = + prepared_srtp_crypto_suite + { + table_writer.write::<_, _, 4>(6, &prepared_srtp_crypto_suite); + } + if let ::core::option::Option::Some(prepared_port) = prepared_port { + table_writer.write::<_, _, 2>(2, &prepared_port); + } + if let ::core::option::Option::Some(prepared_rtcp_mux) = prepared_rtcp_mux { + table_writer.write::<_, _, 1>(3, &prepared_rtcp_mux); + } + if let ::core::option::Option::Some(prepared_comedia) = prepared_comedia { + table_writer.write::<_, _, 1>(4, &prepared_comedia); + } + if let ::core::option::Option::Some(prepared_enable_srtp) = + prepared_enable_srtp + { + table_writer.write::<_, _, 1>(5, &prepared_enable_srtp); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for PlainTransportOptions { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for PlainTransportOptions { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for PlainTransportOptions { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + PlainTransportOptions::create( + builder, + &self.base, + &self.listen_ip, + &self.port, + &self.rtcp_mux, + &self.comedia, + &self.enable_srtp, + &self.srtp_crypto_suite, + ) + } + } + + #[derive(Copy, Clone)] + pub struct PlainTransportOptionsRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> PlainTransportOptionsRef<'a> { + pub fn base( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(0, "PlainTransportOptions", "base") + } + + pub fn listen_ip(&self) -> ::planus::Result> { + self.0 + .access_required(1, "PlainTransportOptions", "listen_ip") + } + + pub fn port(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "PlainTransportOptions", "port")? + .unwrap_or(0), + ) + } + + pub fn rtcp_mux(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(3, "PlainTransportOptions", "rtcp_mux")? + .unwrap_or(false), + ) + } + + pub fn comedia(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(4, "PlainTransportOptions", "comedia")? + .unwrap_or(false), + ) + } + + pub fn enable_srtp(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(5, "PlainTransportOptions", "enable_srtp")? + .unwrap_or(false), + ) + } + + pub fn srtp_crypto_suite( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0 + .access(6, "PlainTransportOptions", "srtp_crypto_suite") + } + } + + impl<'a> ::core::fmt::Debug for PlainTransportOptionsRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("PlainTransportOptionsRef"); + if let ::core::option::Option::Some(field_base) = self.base().transpose() { + f.field("base", &field_base); + } + f.field("listen_ip", &self.listen_ip()); + f.field("port", &self.port()); + f.field("rtcp_mux", &self.rtcp_mux()); + f.field("comedia", &self.comedia()); + f.field("enable_srtp", &self.enable_srtp()); + if let ::core::option::Option::Some(field_srtp_crypto_suite) = + self.srtp_crypto_suite().transpose() + { + f.field("srtp_crypto_suite", &field_srtp_crypto_suite); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for PlainTransportOptions { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: PlainTransportOptionsRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: if let ::core::option::Option::Some(base) = value.base()? { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(base)?, + )) + } else { + ::core::option::Option::None + }, + listen_ip: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.listen_ip()?)?, + ), + port: ::core::convert::TryInto::try_into(value.port()?)?, + rtcp_mux: ::core::convert::TryInto::try_into(value.rtcp_mux()?)?, + comedia: ::core::convert::TryInto::try_into(value.comedia()?)?, + enable_srtp: ::core::convert::TryInto::try_into(value.enable_srtp()?)?, + srtp_crypto_suite: if let ::core::option::Option::Some(srtp_crypto_suite) = + value.srtp_crypto_suite()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + srtp_crypto_suite, + )?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for PlainTransportOptionsRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for PlainTransportOptionsRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[PlainTransportOptionsRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for PlainTransportOptions { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for PlainTransportOptionsRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[PlainTransportOptionsRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ConnectRequest { + pub ip: ::core::option::Option<::planus::alloc::string::String>, + pub port: ::core::option::Option, + pub rtcp_port: ::core::option::Option, + pub srtp_parameters: ::core::option::Option< + ::planus::alloc::boxed::Box, + >, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for ConnectRequest { + fn default() -> Self { + Self { + ip: ::core::default::Default::default(), + port: ::core::default::Default::default(), + rtcp_port: ::core::default::Default::default(), + srtp_parameters: ::core::default::Default::default(), + } + } + } + + impl ConnectRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ip: impl ::planus::WriteAsOptional<::planus::Offset<::core::primitive::str>>, + field_port: impl ::planus::WriteAsOptional, + field_rtcp_port: impl ::planus::WriteAsOptional, + field_srtp_parameters: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_ip = field_ip.prepare(builder); + + let prepared_port = field_port.prepare(builder); + + let prepared_rtcp_port = field_rtcp_port.prepare(builder); + + let prepared_srtp_parameters = field_srtp_parameters.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<10, 12>::new(builder); + + if prepared_ip.is_some() { + table_writer.calculate_size::<::planus::Offset>(2); + } + if prepared_port.is_some() { + table_writer.calculate_size::(4); + } + if prepared_rtcp_port.is_some() { + table_writer.calculate_size::(6); + } + if prepared_srtp_parameters.is_some() { + table_writer + .calculate_size::<::planus::Offset>( + 8, + ); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_ip) = prepared_ip { + table_writer.write::<_, _, 4>(0, &prepared_ip); + } + if let ::core::option::Option::Some(prepared_srtp_parameters) = + prepared_srtp_parameters + { + table_writer.write::<_, _, 4>(3, &prepared_srtp_parameters); + } + if let ::core::option::Option::Some(prepared_port) = prepared_port { + table_writer.write::<_, _, 2>(1, &prepared_port); + } + if let ::core::option::Option::Some(prepared_rtcp_port) = prepared_rtcp_port + { + table_writer.write::<_, _, 2>(2, &prepared_rtcp_port); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ConnectRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ConnectRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ConnectRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ConnectRequest::create( + builder, + &self.ip, + &self.port, + &self.rtcp_port, + &self.srtp_parameters, + ) + } + } + + #[derive(Copy, Clone)] + pub struct ConnectRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ConnectRequestRef<'a> { + pub fn ip( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(0, "ConnectRequest", "ip") + } + + pub fn port(&self) -> ::planus::Result<::core::option::Option> { + self.0.access(1, "ConnectRequest", "port") + } + + pub fn rtcp_port(&self) -> ::planus::Result<::core::option::Option> { + self.0.access(2, "ConnectRequest", "rtcp_port") + } + + pub fn srtp_parameters( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(3, "ConnectRequest", "srtp_parameters") + } + } + + impl<'a> ::core::fmt::Debug for ConnectRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ConnectRequestRef"); + if let ::core::option::Option::Some(field_ip) = self.ip().transpose() { + f.field("ip", &field_ip); + } + if let ::core::option::Option::Some(field_port) = self.port().transpose() { + f.field("port", &field_port); + } + if let ::core::option::Option::Some(field_rtcp_port) = + self.rtcp_port().transpose() + { + f.field("rtcp_port", &field_rtcp_port); + } + if let ::core::option::Option::Some(field_srtp_parameters) = + self.srtp_parameters().transpose() + { + f.field("srtp_parameters", &field_srtp_parameters); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ConnectRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ConnectRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ip: if let ::core::option::Option::Some(ip) = value.ip()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(ip)?) + } else { + ::core::option::Option::None + }, + port: if let ::core::option::Option::Some(port) = value.port()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(port)?) + } else { + ::core::option::Option::None + }, + rtcp_port: if let ::core::option::Option::Some(rtcp_port) = + value.rtcp_port()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + rtcp_port, + )?) + } else { + ::core::option::Option::None + }, + srtp_parameters: if let ::core::option::Option::Some(srtp_parameters) = + value.srtp_parameters()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(srtp_parameters)?, + )) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ConnectRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ConnectRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ConnectRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ConnectRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ConnectRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ConnectRequestRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ConnectResponse { + pub tuple: ::planus::alloc::boxed::Box, + pub rtcp_tuple: + ::core::option::Option<::planus::alloc::boxed::Box>, + pub srtp_parameters: ::core::option::Option< + ::planus::alloc::boxed::Box, + >, + } + + impl ConnectResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_tuple: impl ::planus::WriteAs<::planus::Offset>, + field_rtcp_tuple: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + field_srtp_parameters: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_tuple = field_tuple.prepare(builder); + + let prepared_rtcp_tuple = field_rtcp_tuple.prepare(builder); + + let prepared_srtp_parameters = field_srtp_parameters.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<8, 12>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_rtcp_tuple.is_some() { + table_writer.calculate_size::<::planus::Offset>(4); + } + if prepared_srtp_parameters.is_some() { + table_writer + .calculate_size::<::planus::Offset>( + 6, + ); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_tuple); + if let ::core::option::Option::Some(prepared_rtcp_tuple) = + prepared_rtcp_tuple + { + table_writer.write::<_, _, 4>(1, &prepared_rtcp_tuple); + } + if let ::core::option::Option::Some(prepared_srtp_parameters) = + prepared_srtp_parameters + { + table_writer.write::<_, _, 4>(2, &prepared_srtp_parameters); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ConnectResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ConnectResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ConnectResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ConnectResponse::create( + builder, + &self.tuple, + &self.rtcp_tuple, + &self.srtp_parameters, + ) + } + } + + #[derive(Copy, Clone)] + pub struct ConnectResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ConnectResponseRef<'a> { + pub fn tuple(&self) -> ::planus::Result> { + self.0.access_required(0, "ConnectResponse", "tuple") + } + + pub fn rtcp_tuple( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(1, "ConnectResponse", "rtcp_tuple") + } + + pub fn srtp_parameters( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(2, "ConnectResponse", "srtp_parameters") + } + } + + impl<'a> ::core::fmt::Debug for ConnectResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ConnectResponseRef"); + f.field("tuple", &self.tuple()); + if let ::core::option::Option::Some(field_rtcp_tuple) = + self.rtcp_tuple().transpose() + { + f.field("rtcp_tuple", &field_rtcp_tuple); + } + if let ::core::option::Option::Some(field_srtp_parameters) = + self.srtp_parameters().transpose() + { + f.field("srtp_parameters", &field_srtp_parameters); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ConnectResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ConnectResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + tuple: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.tuple()?)?, + ), + rtcp_tuple: if let ::core::option::Option::Some(rtcp_tuple) = + value.rtcp_tuple()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(rtcp_tuple)?, + )) + } else { + ::core::option::Option::None + }, + srtp_parameters: if let ::core::option::Option::Some(srtp_parameters) = + value.srtp_parameters()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(srtp_parameters)?, + )) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ConnectResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ConnectResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ConnectResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ConnectResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ConnectResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ConnectResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct DumpResponse { + pub base: ::planus::alloc::boxed::Box, + pub rtcp_mux: bool, + pub comedia: bool, + pub tuple: + ::core::option::Option<::planus::alloc::boxed::Box>, + pub rtcp_tuple: + ::core::option::Option<::planus::alloc::boxed::Box>, + pub srtp_parameters: ::core::option::Option< + ::planus::alloc::boxed::Box, + >, + } + + impl DumpResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + field_rtcp_mux: impl ::planus::WriteAsDefault, + field_comedia: impl ::planus::WriteAsDefault, + field_tuple: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + field_rtcp_tuple: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + field_srtp_parameters: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let prepared_rtcp_mux = field_rtcp_mux.prepare(builder, &false); + + let prepared_comedia = field_comedia.prepare(builder, &false); + + let prepared_tuple = field_tuple.prepare(builder); + + let prepared_rtcp_tuple = field_rtcp_tuple.prepare(builder); + + let prepared_srtp_parameters = field_srtp_parameters.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<14, 18>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_rtcp_mux.is_some() { + table_writer.calculate_size::(4); + } + if prepared_comedia.is_some() { + table_writer.calculate_size::(6); + } + if prepared_tuple.is_some() { + table_writer.calculate_size::<::planus::Offset>(8); + } + if prepared_rtcp_tuple.is_some() { + table_writer + .calculate_size::<::planus::Offset>(10); + } + if prepared_srtp_parameters.is_some() { + table_writer + .calculate_size::<::planus::Offset>( + 12, + ); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_base); + if let ::core::option::Option::Some(prepared_tuple) = prepared_tuple { + table_writer.write::<_, _, 4>(3, &prepared_tuple); + } + if let ::core::option::Option::Some(prepared_rtcp_tuple) = + prepared_rtcp_tuple + { + table_writer.write::<_, _, 4>(4, &prepared_rtcp_tuple); + } + if let ::core::option::Option::Some(prepared_srtp_parameters) = + prepared_srtp_parameters + { + table_writer.write::<_, _, 4>(5, &prepared_srtp_parameters); + } + if let ::core::option::Option::Some(prepared_rtcp_mux) = prepared_rtcp_mux { + table_writer.write::<_, _, 1>(1, &prepared_rtcp_mux); + } + if let ::core::option::Option::Some(prepared_comedia) = prepared_comedia { + table_writer.write::<_, _, 1>(2, &prepared_comedia); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for DumpResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + DumpResponse::create( + builder, + &self.base, + &self.rtcp_mux, + &self.comedia, + &self.tuple, + &self.rtcp_tuple, + &self.srtp_parameters, + ) + } + } + + #[derive(Copy, Clone)] + pub struct DumpResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DumpResponseRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "DumpResponse", "base") + } + + pub fn rtcp_mux(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "DumpResponse", "rtcp_mux")? + .unwrap_or(false), + ) + } + + pub fn comedia(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "DumpResponse", "comedia")? + .unwrap_or(false), + ) + } + + pub fn tuple( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(3, "DumpResponse", "tuple") + } + + pub fn rtcp_tuple( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(4, "DumpResponse", "rtcp_tuple") + } + + pub fn srtp_parameters( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(5, "DumpResponse", "srtp_parameters") + } + } + + impl<'a> ::core::fmt::Debug for DumpResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DumpResponseRef"); + f.field("base", &self.base()); + f.field("rtcp_mux", &self.rtcp_mux()); + f.field("comedia", &self.comedia()); + if let ::core::option::Option::Some(field_tuple) = self.tuple().transpose() { + f.field("tuple", &field_tuple); + } + if let ::core::option::Option::Some(field_rtcp_tuple) = + self.rtcp_tuple().transpose() + { + f.field("rtcp_tuple", &field_rtcp_tuple); + } + if let ::core::option::Option::Some(field_srtp_parameters) = + self.srtp_parameters().transpose() + { + f.field("srtp_parameters", &field_srtp_parameters); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for DumpResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DumpResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + rtcp_mux: ::core::convert::TryInto::try_into(value.rtcp_mux()?)?, + comedia: ::core::convert::TryInto::try_into(value.comedia()?)?, + tuple: if let ::core::option::Option::Some(tuple) = value.tuple()? { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(tuple)?, + )) + } else { + ::core::option::Option::None + }, + rtcp_tuple: if let ::core::option::Option::Some(rtcp_tuple) = + value.rtcp_tuple()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(rtcp_tuple)?, + )) + } else { + ::core::option::Option::None + }, + srtp_parameters: if let ::core::option::Option::Some(srtp_parameters) = + value.srtp_parameters()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(srtp_parameters)?, + )) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DumpResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DumpResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DumpResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for DumpResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DumpResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[DumpResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct GetStatsResponse { + pub base: ::planus::alloc::boxed::Box, + pub rtcp_mux: bool, + pub comedia: bool, + pub tuple: ::planus::alloc::boxed::Box, + pub rtcp_tuple: + ::core::option::Option<::planus::alloc::boxed::Box>, + } + + impl GetStatsResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + field_rtcp_mux: impl ::planus::WriteAsDefault, + field_comedia: impl ::planus::WriteAsDefault, + field_tuple: impl ::planus::WriteAs<::planus::Offset>, + field_rtcp_tuple: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let prepared_rtcp_mux = field_rtcp_mux.prepare(builder, &false); + + let prepared_comedia = field_comedia.prepare(builder, &false); + + let prepared_tuple = field_tuple.prepare(builder); + + let prepared_rtcp_tuple = field_rtcp_tuple.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<12, 14>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_rtcp_mux.is_some() { + table_writer.calculate_size::(4); + } + if prepared_comedia.is_some() { + table_writer.calculate_size::(6); + } + table_writer.calculate_size::<::planus::Offset>(8); + if prepared_rtcp_tuple.is_some() { + table_writer + .calculate_size::<::planus::Offset>(10); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_base); + table_writer.write::<_, _, 4>(3, &prepared_tuple); + if let ::core::option::Option::Some(prepared_rtcp_tuple) = + prepared_rtcp_tuple + { + table_writer.write::<_, _, 4>(4, &prepared_rtcp_tuple); + } + if let ::core::option::Option::Some(prepared_rtcp_mux) = prepared_rtcp_mux { + table_writer.write::<_, _, 1>(1, &prepared_rtcp_mux); + } + if let ::core::option::Option::Some(prepared_comedia) = prepared_comedia { + table_writer.write::<_, _, 1>(2, &prepared_comedia); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for GetStatsResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + GetStatsResponse::create( + builder, + &self.base, + &self.rtcp_mux, + &self.comedia, + &self.tuple, + &self.rtcp_tuple, + ) + } + } + + #[derive(Copy, Clone)] + pub struct GetStatsResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> GetStatsResponseRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "GetStatsResponse", "base") + } + + pub fn rtcp_mux(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(1, "GetStatsResponse", "rtcp_mux")? + .unwrap_or(false), + ) + } + + pub fn comedia(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "GetStatsResponse", "comedia")? + .unwrap_or(false), + ) + } + + pub fn tuple(&self) -> ::planus::Result> { + self.0.access_required(3, "GetStatsResponse", "tuple") + } + + pub fn rtcp_tuple( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(4, "GetStatsResponse", "rtcp_tuple") + } + } + + impl<'a> ::core::fmt::Debug for GetStatsResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("GetStatsResponseRef"); + f.field("base", &self.base()); + f.field("rtcp_mux", &self.rtcp_mux()); + f.field("comedia", &self.comedia()); + f.field("tuple", &self.tuple()); + if let ::core::option::Option::Some(field_rtcp_tuple) = + self.rtcp_tuple().transpose() + { + f.field("rtcp_tuple", &field_rtcp_tuple); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for GetStatsResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: GetStatsResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + rtcp_mux: ::core::convert::TryInto::try_into(value.rtcp_mux()?)?, + comedia: ::core::convert::TryInto::try_into(value.comedia()?)?, + tuple: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.tuple()?)?, + ), + rtcp_tuple: if let ::core::option::Option::Some(rtcp_tuple) = + value.rtcp_tuple()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(rtcp_tuple)?, + )) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for GetStatsResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for GetStatsResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[GetStatsResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for GetStatsResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for GetStatsResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[GetStatsResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct TupleNotification { + pub tuple: ::planus::alloc::boxed::Box, + } + + impl TupleNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_tuple: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_tuple = field_tuple.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_tuple); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for TupleNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for TupleNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for TupleNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + TupleNotification::create(builder, &self.tuple) + } + } + + #[derive(Copy, Clone)] + pub struct TupleNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> TupleNotificationRef<'a> { + pub fn tuple(&self) -> ::planus::Result> { + self.0.access_required(0, "TupleNotification", "tuple") + } + } + + impl<'a> ::core::fmt::Debug for TupleNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("TupleNotificationRef"); + f.field("tuple", &self.tuple()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for TupleNotification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: TupleNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + tuple: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.tuple()?)?, + ), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for TupleNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for TupleNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[TupleNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for TupleNotification { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for TupleNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[TupleNotificationRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct RtcpTupleNotification { + pub tuple: ::planus::alloc::boxed::Box, + } + + impl RtcpTupleNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_tuple: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_tuple = field_tuple.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_tuple); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RtcpTupleNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RtcpTupleNotification { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RtcpTupleNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + RtcpTupleNotification::create(builder, &self.tuple) + } + } + + #[derive(Copy, Clone)] + pub struct RtcpTupleNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RtcpTupleNotificationRef<'a> { + pub fn tuple(&self) -> ::planus::Result> { + self.0.access_required(0, "RtcpTupleNotification", "tuple") + } + } + + impl<'a> ::core::fmt::Debug for RtcpTupleNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RtcpTupleNotificationRef"); + f.field("tuple", &self.tuple()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RtcpTupleNotification { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RtcpTupleNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + tuple: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.tuple()?)?, + ), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RtcpTupleNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RtcpTupleNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RtcpTupleNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RtcpTupleNotification { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RtcpTupleNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[RtcpTupleNotificationRef]", + "read_as_root", + 0, + ) + }) + } + } + } + pub mod web_rtc_transport { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ListenIndividual { + pub listen_ips: ::planus::alloc::vec::Vec, + pub port: u16, + } + + impl ListenIndividual { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_listen_ips: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_port: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_listen_ips = field_listen_ips.prepare(builder); + + let prepared_port = field_port.prepare(builder, &0); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 6>::new(builder); + + table_writer.calculate_size::<::planus::Offset<[::planus::Offset]>>(2); + if prepared_port.is_some() { + table_writer.calculate_size::(4); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_listen_ips); + if let ::core::option::Option::Some(prepared_port) = prepared_port { + table_writer.write::<_, _, 2>(1, &prepared_port); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ListenIndividual { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ListenIndividual { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ListenIndividual { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ListenIndividual::create(builder, &self.listen_ips, &self.port) + } + } + + #[derive(Copy, Clone)] + pub struct ListenIndividualRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ListenIndividualRef<'a> { + pub fn listen_ips( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result>>, + > { + self.0.access_required(0, "ListenIndividual", "listen_ips") + } + + pub fn port(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(1, "ListenIndividual", "port")?.unwrap_or(0), + ) + } + } + + impl<'a> ::core::fmt::Debug for ListenIndividualRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ListenIndividualRef"); + f.field("listen_ips", &self.listen_ips()); + f.field("port", &self.port()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ListenIndividual { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ListenIndividualRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + listen_ips: value.listen_ips()?.to_vec_result()?, + port: ::core::convert::TryInto::try_into(value.port()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ListenIndividualRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ListenIndividualRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ListenIndividualRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ListenIndividual { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ListenIndividualRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ListenIndividualRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ListenServer { + pub web_rtc_server_id: ::planus::alloc::string::String, + } + + impl ListenServer { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_web_rtc_server_id: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_web_rtc_server_id = field_web_rtc_server_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_web_rtc_server_id); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ListenServer { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ListenServer { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ListenServer { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ListenServer::create(builder, &self.web_rtc_server_id) + } + } + + #[derive(Copy, Clone)] + pub struct ListenServerRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ListenServerRef<'a> { + pub fn web_rtc_server_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "ListenServer", "web_rtc_server_id") + } + } + + impl<'a> ::core::fmt::Debug for ListenServerRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ListenServerRef"); + f.field("web_rtc_server_id", &self.web_rtc_server_id()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ListenServer { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ListenServerRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + web_rtc_server_id: ::core::convert::TryInto::try_into( + value.web_rtc_server_id()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ListenServerRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ListenServerRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ListenServerRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ListenServer { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ListenServerRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ListenServerRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub enum Listen { + ListenIndividual(::planus::alloc::boxed::Box), + ListenServer(::planus::alloc::boxed::Box), + } + + impl Listen { + pub fn create_listen_individual( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(1, value.prepare(builder).downcast()) + } + + pub fn create_listen_server( + builder: &mut ::planus::Builder, + value: impl ::planus::WriteAsOffset, + ) -> ::planus::UnionOffset { + ::planus::UnionOffset::new(2, value.prepare(builder).downcast()) + } + } + + impl ::planus::WriteAsUnion for Listen { + fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::UnionOffset { + match self { + Self::ListenIndividual(value) => { + Self::create_listen_individual(builder, value) + } + Self::ListenServer(value) => Self::create_listen_server(builder, value), + } + } + } + + impl ::planus::WriteAsOptionalUnion for Listen { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::UnionOffset> { + ::core::option::Option::Some(::planus::WriteAsUnion::prepare(self, builder)) + } + } + + #[derive(Copy, Clone, Debug)] + pub enum ListenRef<'a> { + ListenIndividual(self::ListenIndividualRef<'a>), + ListenServer(self::ListenServerRef<'a>), + } + + impl<'a> ::core::convert::TryFrom> for Listen { + type Error = ::planus::Error; + + fn try_from(value: ListenRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(match value { + ListenRef::ListenIndividual(value) => { + Listen::ListenIndividual(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + + ListenRef::ListenServer(value) => { + Listen::ListenServer(::planus::alloc::boxed::Box::new( + ::core::convert::TryFrom::try_from(value)?, + )) + } + }) + } + } + + impl<'a> ::planus::TableReadUnion<'a> for ListenRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + field_offset: usize, + tag: u8, + ) -> ::core::result::Result { + match tag { + 1 => ::core::result::Result::Ok(Self::ListenIndividual( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + 2 => ::core::result::Result::Ok(Self::ListenServer( + ::planus::TableRead::from_buffer(buffer, field_offset)?, + )), + _ => ::core::result::Result::Err( + ::planus::errors::ErrorKind::UnknownUnionTag { tag }, + ), + } + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct WebRtcTransportOptions { + pub base: ::planus::alloc::boxed::Box, + pub listen: self::Listen, + pub enable_udp: bool, + pub enable_tcp: bool, + pub prefer_udp: bool, + pub prefer_tcp: bool, + } + + impl WebRtcTransportOptions { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + field_listen: impl ::planus::WriteAsUnion, + field_enable_udp: impl ::planus::WriteAsDefault, + field_enable_tcp: impl ::planus::WriteAsDefault, + field_prefer_udp: impl ::planus::WriteAsDefault, + field_prefer_tcp: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let prepared_listen = field_listen.prepare(builder); + + let prepared_enable_udp = field_enable_udp.prepare(builder, &true); + + let prepared_enable_tcp = field_enable_tcp.prepare(builder, &false); + + let prepared_prefer_udp = field_prefer_udp.prepare(builder, &false); + + let prepared_prefer_tcp = field_prefer_tcp.prepare(builder, &false); + + let mut table_writer = + ::planus::table_writer::TableWriter::<16, 13>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::(4); + table_writer.calculate_size::<::planus::Offset>(6); + if prepared_enable_udp.is_some() { + table_writer.calculate_size::(8); + } + if prepared_enable_tcp.is_some() { + table_writer.calculate_size::(10); + } + if prepared_prefer_udp.is_some() { + table_writer.calculate_size::(12); + } + if prepared_prefer_tcp.is_some() { + table_writer.calculate_size::(14); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_base); + table_writer.write::<_, _, 4>(2, &prepared_listen.offset()); + table_writer.write::<_, _, 1>(1, &prepared_listen.tag()); + if let ::core::option::Option::Some(prepared_enable_udp) = + prepared_enable_udp + { + table_writer.write::<_, _, 1>(3, &prepared_enable_udp); + } + if let ::core::option::Option::Some(prepared_enable_tcp) = + prepared_enable_tcp + { + table_writer.write::<_, _, 1>(4, &prepared_enable_tcp); + } + if let ::core::option::Option::Some(prepared_prefer_udp) = + prepared_prefer_udp + { + table_writer.write::<_, _, 1>(5, &prepared_prefer_udp); + } + if let ::core::option::Option::Some(prepared_prefer_tcp) = + prepared_prefer_tcp + { + table_writer.write::<_, _, 1>(6, &prepared_prefer_tcp); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for WebRtcTransportOptions { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for WebRtcTransportOptions + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for WebRtcTransportOptions { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + WebRtcTransportOptions::create( + builder, + &self.base, + &self.listen, + &self.enable_udp, + &self.enable_tcp, + &self.prefer_udp, + &self.prefer_tcp, + ) + } + } + + #[derive(Copy, Clone)] + pub struct WebRtcTransportOptionsRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> WebRtcTransportOptionsRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "WebRtcTransportOptions", "base") + } + + pub fn listen(&self) -> ::planus::Result> { + self.0 + .access_union_required(1, "WebRtcTransportOptions", "listen") + } + + pub fn enable_udp(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(3, "WebRtcTransportOptions", "enable_udp")? + .unwrap_or(true), + ) + } + + pub fn enable_tcp(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(4, "WebRtcTransportOptions", "enable_tcp")? + .unwrap_or(false), + ) + } + + pub fn prefer_udp(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(5, "WebRtcTransportOptions", "prefer_udp")? + .unwrap_or(false), + ) + } + + pub fn prefer_tcp(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(6, "WebRtcTransportOptions", "prefer_tcp")? + .unwrap_or(false), + ) + } + } + + impl<'a> ::core::fmt::Debug for WebRtcTransportOptionsRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("WebRtcTransportOptionsRef"); + f.field("base", &self.base()); + f.field("listen", &self.listen()); + f.field("enable_udp", &self.enable_udp()); + f.field("enable_tcp", &self.enable_tcp()); + f.field("prefer_udp", &self.prefer_udp()); + f.field("prefer_tcp", &self.prefer_tcp()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for WebRtcTransportOptions { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: WebRtcTransportOptionsRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + listen: ::core::convert::TryInto::try_into(value.listen()?)?, + enable_udp: ::core::convert::TryInto::try_into(value.enable_udp()?)?, + enable_tcp: ::core::convert::TryInto::try_into(value.enable_tcp()?)?, + prefer_udp: ::core::convert::TryInto::try_into(value.prefer_udp()?)?, + prefer_tcp: ::core::convert::TryInto::try_into(value.prefer_tcp()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for WebRtcTransportOptionsRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for WebRtcTransportOptionsRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[WebRtcTransportOptionsRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for WebRtcTransportOptions { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for WebRtcTransportOptionsRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[WebRtcTransportOptionsRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct Fingerprint { + pub algorithm: ::planus::alloc::string::String, + pub value: ::planus::alloc::string::String, + } + + impl Fingerprint { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_algorithm: impl ::planus::WriteAs<::planus::Offset>, + field_value: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_algorithm = field_algorithm.prepare(builder); + + let prepared_value = field_value.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_algorithm); + table_writer.write::<_, _, 4>(1, &prepared_value); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for Fingerprint { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for Fingerprint { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for Fingerprint { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + Fingerprint::create(builder, &self.algorithm, &self.value) + } + } + + #[derive(Copy, Clone)] + pub struct FingerprintRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> FingerprintRef<'a> { + pub fn algorithm(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "Fingerprint", "algorithm") + } + + pub fn value(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "Fingerprint", "value") + } + } + + impl<'a> ::core::fmt::Debug for FingerprintRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("FingerprintRef"); + f.field("algorithm", &self.algorithm()); + f.field("value", &self.value()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for Fingerprint { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: FingerprintRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + algorithm: ::core::convert::TryInto::try_into(value.algorithm()?)?, + value: ::core::convert::TryInto::try_into(value.value()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for FingerprintRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for FingerprintRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[FingerprintRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for Fingerprint { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for FingerprintRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[FingerprintRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct DtlsParameters { + pub fingerprints: ::planus::alloc::vec::Vec, + pub role: ::core::option::Option<::planus::alloc::string::String>, + } + + impl DtlsParameters { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_fingerprints: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_role: impl ::planus::WriteAsOptional<::planus::Offset<::core::primitive::str>>, + ) -> ::planus::Offset { + let prepared_fingerprints = field_fingerprints.prepare(builder); + + let prepared_role = field_role.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 8>::new(builder); + + table_writer + .calculate_size::<::planus::Offset<[::planus::Offset]>>( + 2, + ); + if prepared_role.is_some() { + table_writer.calculate_size::<::planus::Offset>(4); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_fingerprints); + if let ::core::option::Option::Some(prepared_role) = prepared_role { + table_writer.write::<_, _, 4>(1, &prepared_role); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for DtlsParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for DtlsParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for DtlsParameters { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + DtlsParameters::create(builder, &self.fingerprints, &self.role) + } + } + + #[derive(Copy, Clone)] + pub struct DtlsParametersRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DtlsParametersRef<'a> { + pub fn fingerprints( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result>>, + > { + self.0.access_required(0, "DtlsParameters", "fingerprints") + } + + pub fn role( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(1, "DtlsParameters", "role") + } + } + + impl<'a> ::core::fmt::Debug for DtlsParametersRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DtlsParametersRef"); + f.field("fingerprints", &self.fingerprints()); + if let ::core::option::Option::Some(field_role) = self.role().transpose() { + f.field("role", &field_role); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for DtlsParameters { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DtlsParametersRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + fingerprints: value.fingerprints()?.to_vec_result()?, + role: if let ::core::option::Option::Some(role) = value.role()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(role)?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DtlsParametersRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DtlsParametersRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DtlsParametersRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for DtlsParameters { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DtlsParametersRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[DtlsParametersRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct IceParameters { + pub username_fragment: ::planus::alloc::string::String, + pub password: ::planus::alloc::string::String, + pub ice_lite: bool, + } + + impl IceParameters { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_username_fragment: impl ::planus::WriteAs<::planus::Offset>, + field_password: impl ::planus::WriteAs<::planus::Offset>, + field_ice_lite: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_username_fragment = field_username_fragment.prepare(builder); + + let prepared_password = field_password.prepare(builder); + + let prepared_ice_lite = field_ice_lite.prepare(builder, &true); + + let mut table_writer = + ::planus::table_writer::TableWriter::<8, 9>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + if prepared_ice_lite.is_some() { + table_writer.calculate_size::(6); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_username_fragment); + table_writer.write::<_, _, 4>(1, &prepared_password); + if let ::core::option::Option::Some(prepared_ice_lite) = prepared_ice_lite { + table_writer.write::<_, _, 1>(2, &prepared_ice_lite); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for IceParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for IceParameters { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for IceParameters { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + IceParameters::create( + builder, + &self.username_fragment, + &self.password, + &self.ice_lite, + ) + } + } + + #[derive(Copy, Clone)] + pub struct IceParametersRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> IceParametersRef<'a> { + pub fn username_fragment(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "IceParameters", "username_fragment") + } + + pub fn password(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "IceParameters", "password") + } + + pub fn ice_lite(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(2, "IceParameters", "ice_lite")? + .unwrap_or(true), + ) + } + } + + impl<'a> ::core::fmt::Debug for IceParametersRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("IceParametersRef"); + f.field("username_fragment", &self.username_fragment()); + f.field("password", &self.password()); + f.field("ice_lite", &self.ice_lite()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for IceParameters { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: IceParametersRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + username_fragment: ::core::convert::TryInto::try_into( + value.username_fragment()?, + )?, + password: ::core::convert::TryInto::try_into(value.password()?)?, + ice_lite: ::core::convert::TryInto::try_into(value.ice_lite()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for IceParametersRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for IceParametersRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[IceParametersRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for IceParameters { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for IceParametersRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[IceParametersRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct IceCandidate { + pub foundation: ::planus::alloc::string::String, + pub priority: u32, + pub ip: ::planus::alloc::string::String, + pub protocol: ::planus::alloc::string::String, + pub port: u16, + pub type_: ::core::option::Option<::planus::alloc::string::String>, + pub tcp_type: ::core::option::Option<::planus::alloc::string::String>, + } + + impl IceCandidate { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_foundation: impl ::planus::WriteAs<::planus::Offset>, + field_priority: impl ::planus::WriteAsDefault, + field_ip: impl ::planus::WriteAs<::planus::Offset>, + field_protocol: impl ::planus::WriteAs<::planus::Offset>, + field_port: impl ::planus::WriteAsDefault, + field_type_: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + field_tcp_type: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + ) -> ::planus::Offset { + let prepared_foundation = field_foundation.prepare(builder); + + let prepared_priority = field_priority.prepare(builder, &0); + + let prepared_ip = field_ip.prepare(builder); + + let prepared_protocol = field_protocol.prepare(builder); + + let prepared_port = field_port.prepare(builder, &0); + + let prepared_type_ = field_type_.prepare(builder); + + let prepared_tcp_type = field_tcp_type.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<16, 26>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + if prepared_priority.is_some() { + table_writer.calculate_size::(4); + } + table_writer.calculate_size::<::planus::Offset>(6); + table_writer.calculate_size::<::planus::Offset>(8); + if prepared_port.is_some() { + table_writer.calculate_size::(10); + } + if prepared_type_.is_some() { + table_writer.calculate_size::<::planus::Offset>(12); + } + if prepared_tcp_type.is_some() { + table_writer.calculate_size::<::planus::Offset>(14); + } + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_foundation); + if let ::core::option::Option::Some(prepared_priority) = prepared_priority { + table_writer.write::<_, _, 4>(1, &prepared_priority); + } + table_writer.write::<_, _, 4>(2, &prepared_ip); + table_writer.write::<_, _, 4>(3, &prepared_protocol); + if let ::core::option::Option::Some(prepared_type_) = prepared_type_ { + table_writer.write::<_, _, 4>(5, &prepared_type_); + } + if let ::core::option::Option::Some(prepared_tcp_type) = prepared_tcp_type { + table_writer.write::<_, _, 4>(6, &prepared_tcp_type); + } + if let ::core::option::Option::Some(prepared_port) = prepared_port { + table_writer.write::<_, _, 2>(4, &prepared_port); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for IceCandidate { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for IceCandidate { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for IceCandidate { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + IceCandidate::create( + builder, + &self.foundation, + &self.priority, + &self.ip, + &self.protocol, + &self.port, + &self.type_, + &self.tcp_type, + ) + } + } + + #[derive(Copy, Clone)] + pub struct IceCandidateRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> IceCandidateRef<'a> { + pub fn foundation(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(0, "IceCandidate", "foundation") + } + + pub fn priority(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(1, "IceCandidate", "priority")?.unwrap_or(0), + ) + } + + pub fn ip(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(2, "IceCandidate", "ip") + } + + pub fn protocol(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(3, "IceCandidate", "protocol") + } + + pub fn port(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0.access(4, "IceCandidate", "port")?.unwrap_or(0), + ) + } + + pub fn type_( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(5, "IceCandidate", "type_") + } + + pub fn tcp_type( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0.access(6, "IceCandidate", "tcp_type") + } + } + + impl<'a> ::core::fmt::Debug for IceCandidateRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("IceCandidateRef"); + f.field("foundation", &self.foundation()); + f.field("priority", &self.priority()); + f.field("ip", &self.ip()); + f.field("protocol", &self.protocol()); + f.field("port", &self.port()); + if let ::core::option::Option::Some(field_type_) = self.type_().transpose() { + f.field("type_", &field_type_); + } + if let ::core::option::Option::Some(field_tcp_type) = + self.tcp_type().transpose() + { + f.field("tcp_type", &field_tcp_type); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for IceCandidate { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: IceCandidateRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + foundation: ::core::convert::TryInto::try_into(value.foundation()?)?, + priority: ::core::convert::TryInto::try_into(value.priority()?)?, + ip: ::core::convert::TryInto::try_into(value.ip()?)?, + protocol: ::core::convert::TryInto::try_into(value.protocol()?)?, + port: ::core::convert::TryInto::try_into(value.port()?)?, + type_: if let ::core::option::Option::Some(type_) = value.type_()? { + ::core::option::Option::Some(::core::convert::TryInto::try_into(type_)?) + } else { + ::core::option::Option::None + }, + tcp_type: if let ::core::option::Option::Some(tcp_type) = + value.tcp_type()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + tcp_type, + )?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for IceCandidateRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for IceCandidateRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[IceCandidateRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for IceCandidate { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for IceCandidateRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[IceCandidateRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ConnectRequest { + pub dtls_parameters: ::planus::alloc::boxed::Box, + } + + impl ConnectRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_dtls_parameters: impl ::planus::WriteAs< + ::planus::Offset, + >, + ) -> ::planus::Offset { + let prepared_dtls_parameters = field_dtls_parameters.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_dtls_parameters); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ConnectRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ConnectRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ConnectRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ConnectRequest::create(builder, &self.dtls_parameters) + } + } + + #[derive(Copy, Clone)] + pub struct ConnectRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ConnectRequestRef<'a> { + pub fn dtls_parameters(&self) -> ::planus::Result> { + self.0 + .access_required(0, "ConnectRequest", "dtls_parameters") + } + } + + impl<'a> ::core::fmt::Debug for ConnectRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ConnectRequestRef"); + f.field("dtls_parameters", &self.dtls_parameters()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ConnectRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ConnectRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + dtls_parameters: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.dtls_parameters()?)?, + ), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ConnectRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ConnectRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ConnectRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ConnectRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ConnectRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ConnectRequestRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct ConnectResponse { + pub dtls_local_role: ::planus::alloc::string::String, + } + + impl ConnectResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_dtls_local_role: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_dtls_local_role = field_dtls_local_role.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_dtls_local_role); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for ConnectResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for ConnectResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for ConnectResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ConnectResponse::create(builder, &self.dtls_local_role) + } + } + + #[derive(Copy, Clone)] + pub struct ConnectResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> ConnectResponseRef<'a> { + pub fn dtls_local_role(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "ConnectResponse", "dtls_local_role") + } + } + + impl<'a> ::core::fmt::Debug for ConnectResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("ConnectResponseRef"); + f.field("dtls_local_role", &self.dtls_local_role()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for ConnectResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: ConnectResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + dtls_local_role: ::core::convert::TryInto::try_into( + value.dtls_local_role()?, + )?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for ConnectResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for ConnectResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[ConnectResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for ConnectResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for ConnectResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[ConnectResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct DumpResponse { + pub base: ::planus::alloc::boxed::Box, + pub ice_role: ::planus::alloc::string::String, + pub ice_parameters: ::planus::alloc::boxed::Box, + pub ice_candidates: ::planus::alloc::vec::Vec, + pub ice_state: ::planus::alloc::string::String, + pub ice_selected_tuple: + ::core::option::Option<::planus::alloc::boxed::Box>, + pub dtls_parameters: ::planus::alloc::boxed::Box, + pub dtls_state: ::planus::alloc::string::String, + } + + impl DumpResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + field_ice_role: impl ::planus::WriteAs<::planus::Offset>, + field_ice_parameters: impl ::planus::WriteAs<::planus::Offset>, + field_ice_candidates: impl ::planus::WriteAs< + ::planus::Offset<[::planus::Offset]>, + >, + field_ice_state: impl ::planus::WriteAs<::planus::Offset>, + field_ice_selected_tuple: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + field_dtls_parameters: impl ::planus::WriteAs< + ::planus::Offset, + >, + field_dtls_state: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let prepared_ice_role = field_ice_role.prepare(builder); + + let prepared_ice_parameters = field_ice_parameters.prepare(builder); + + let prepared_ice_candidates = field_ice_candidates.prepare(builder); + + let prepared_ice_state = field_ice_state.prepare(builder); + + let prepared_ice_selected_tuple = field_ice_selected_tuple.prepare(builder); + + let prepared_dtls_parameters = field_dtls_parameters.prepare(builder); + + let prepared_dtls_state = field_dtls_state.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<18, 32>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + table_writer.calculate_size::<::planus::Offset>(6); + table_writer + .calculate_size::<::planus::Offset<[::planus::Offset]>>( + 8, + ); + table_writer.calculate_size::<::planus::Offset>(10); + if prepared_ice_selected_tuple.is_some() { + table_writer + .calculate_size::<::planus::Offset>(12); + } + table_writer.calculate_size::<::planus::Offset>(14); + table_writer.calculate_size::<::planus::Offset>(16); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_base); + table_writer.write::<_, _, 4>(1, &prepared_ice_role); + table_writer.write::<_, _, 4>(2, &prepared_ice_parameters); + table_writer.write::<_, _, 4>(3, &prepared_ice_candidates); + table_writer.write::<_, _, 4>(4, &prepared_ice_state); + if let ::core::option::Option::Some(prepared_ice_selected_tuple) = + prepared_ice_selected_tuple + { + table_writer.write::<_, _, 4>(5, &prepared_ice_selected_tuple); + } + table_writer.write::<_, _, 4>(6, &prepared_dtls_parameters); + table_writer.write::<_, _, 4>(7, &prepared_dtls_state); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for DumpResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for DumpResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + DumpResponse::create( + builder, + &self.base, + &self.ice_role, + &self.ice_parameters, + &self.ice_candidates, + &self.ice_state, + &self.ice_selected_tuple, + &self.dtls_parameters, + &self.dtls_state, + ) + } + } + + #[derive(Copy, Clone)] + pub struct DumpResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DumpResponseRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "DumpResponse", "base") + } + + pub fn ice_role(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "DumpResponse", "ice_role") + } + + pub fn ice_parameters(&self) -> ::planus::Result> { + self.0.access_required(2, "DumpResponse", "ice_parameters") + } + + pub fn ice_candidates( + &self, + ) -> ::planus::Result< + ::planus::Vector<'a, ::planus::Result>>, + > { + self.0.access_required(3, "DumpResponse", "ice_candidates") + } + + pub fn ice_state(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(4, "DumpResponse", "ice_state") + } + + pub fn ice_selected_tuple( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(5, "DumpResponse", "ice_selected_tuple") + } + + pub fn dtls_parameters(&self) -> ::planus::Result> { + self.0.access_required(6, "DumpResponse", "dtls_parameters") + } + + pub fn dtls_state(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(7, "DumpResponse", "dtls_state") + } + } + + impl<'a> ::core::fmt::Debug for DumpResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DumpResponseRef"); + f.field("base", &self.base()); + f.field("ice_role", &self.ice_role()); + f.field("ice_parameters", &self.ice_parameters()); + f.field("ice_candidates", &self.ice_candidates()); + f.field("ice_state", &self.ice_state()); + if let ::core::option::Option::Some(field_ice_selected_tuple) = + self.ice_selected_tuple().transpose() + { + f.field("ice_selected_tuple", &field_ice_selected_tuple); + } + f.field("dtls_parameters", &self.dtls_parameters()); + f.field("dtls_state", &self.dtls_state()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for DumpResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DumpResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + ice_role: ::core::convert::TryInto::try_into(value.ice_role()?)?, + ice_parameters: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.ice_parameters()?)?, + ), + ice_candidates: value.ice_candidates()?.to_vec_result()?, + ice_state: ::core::convert::TryInto::try_into(value.ice_state()?)?, + ice_selected_tuple: if let ::core::option::Option::Some( + ice_selected_tuple, + ) = value.ice_selected_tuple()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(ice_selected_tuple)?, + )) + } else { + ::core::option::Option::None + }, + dtls_parameters: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.dtls_parameters()?)?, + ), + dtls_state: ::core::convert::TryInto::try_into(value.dtls_state()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DumpResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DumpResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DumpResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for DumpResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DumpResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[DumpResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct GetStatsResponse { + pub base: ::planus::alloc::boxed::Box, + pub ice_role: ::planus::alloc::string::String, + pub ice_state: ::planus::alloc::string::String, + pub ice_selected_tuple: + ::core::option::Option<::planus::alloc::boxed::Box>, + pub dtls_state: ::planus::alloc::string::String, + } + + impl GetStatsResponse { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_base: impl ::planus::WriteAs<::planus::Offset>, + field_ice_role: impl ::planus::WriteAs<::planus::Offset>, + field_ice_state: impl ::planus::WriteAs<::planus::Offset>, + field_ice_selected_tuple: impl ::planus::WriteAsOptional< + ::planus::Offset, + >, + field_dtls_state: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_base = field_base.prepare(builder); + + let prepared_ice_role = field_ice_role.prepare(builder); + + let prepared_ice_state = field_ice_state.prepare(builder); + + let prepared_ice_selected_tuple = field_ice_selected_tuple.prepare(builder); + + let prepared_dtls_state = field_dtls_state.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<12, 20>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + table_writer.calculate_size::<::planus::Offset>(4); + table_writer.calculate_size::<::planus::Offset>(6); + if prepared_ice_selected_tuple.is_some() { + table_writer.calculate_size::<::planus::Offset>(8); + } + table_writer.calculate_size::<::planus::Offset>(10); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_base); + table_writer.write::<_, _, 4>(1, &prepared_ice_role); + table_writer.write::<_, _, 4>(2, &prepared_ice_state); + if let ::core::option::Option::Some(prepared_ice_selected_tuple) = + prepared_ice_selected_tuple + { + table_writer.write::<_, _, 4>(3, &prepared_ice_selected_tuple); + } + table_writer.write::<_, _, 4>(4, &prepared_dtls_state); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for GetStatsResponse { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for GetStatsResponse { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + GetStatsResponse::create( + builder, + &self.base, + &self.ice_role, + &self.ice_state, + &self.ice_selected_tuple, + &self.dtls_state, + ) + } + } + + #[derive(Copy, Clone)] + pub struct GetStatsResponseRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> GetStatsResponseRef<'a> { + pub fn base(&self) -> ::planus::Result> { + self.0.access_required(0, "GetStatsResponse", "base") + } + + pub fn ice_role(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(1, "GetStatsResponse", "ice_role") + } + + pub fn ice_state(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(2, "GetStatsResponse", "ice_state") + } + + pub fn ice_selected_tuple( + &self, + ) -> ::planus::Result<::core::option::Option>> + { + self.0.access(3, "GetStatsResponse", "ice_selected_tuple") + } + + pub fn dtls_state(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0.access_required(4, "GetStatsResponse", "dtls_state") + } + } + + impl<'a> ::core::fmt::Debug for GetStatsResponseRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("GetStatsResponseRef"); + f.field("base", &self.base()); + f.field("ice_role", &self.ice_role()); + f.field("ice_state", &self.ice_state()); + if let ::core::option::Option::Some(field_ice_selected_tuple) = + self.ice_selected_tuple().transpose() + { + f.field("ice_selected_tuple", &field_ice_selected_tuple); + } + f.field("dtls_state", &self.dtls_state()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for GetStatsResponse { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: GetStatsResponseRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + base: ::planus::alloc::boxed::Box::new(::core::convert::TryInto::try_into( + value.base()?, + )?), + ice_role: ::core::convert::TryInto::try_into(value.ice_role()?)?, + ice_state: ::core::convert::TryInto::try_into(value.ice_state()?)?, + ice_selected_tuple: if let ::core::option::Option::Some( + ice_selected_tuple, + ) = value.ice_selected_tuple()? + { + ::core::option::Option::Some(::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(ice_selected_tuple)?, + )) + } else { + ::core::option::Option::None + }, + dtls_state: ::core::convert::TryInto::try_into(value.dtls_state()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for GetStatsResponseRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for GetStatsResponseRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[GetStatsResponseRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for GetStatsResponse { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for GetStatsResponseRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[GetStatsResponseRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct IceSelectedTupleChangeNotification { + pub tuple: ::planus::alloc::boxed::Box, + } + + impl IceSelectedTupleChangeNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_tuple: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_tuple = field_tuple.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_tuple); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for IceSelectedTupleChangeNotification + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for IceSelectedTupleChangeNotification + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset + for IceSelectedTupleChangeNotification + { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + IceSelectedTupleChangeNotification::create(builder, &self.tuple) + } + } + + #[derive(Copy, Clone)] + pub struct IceSelectedTupleChangeNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> IceSelectedTupleChangeNotificationRef<'a> { + pub fn tuple(&self) -> ::planus::Result> { + self.0 + .access_required(0, "IceSelectedTupleChangeNotification", "tuple") + } + } + + impl<'a> ::core::fmt::Debug for IceSelectedTupleChangeNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("IceSelectedTupleChangeNotificationRef"); + f.field("tuple", &self.tuple()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for IceSelectedTupleChangeNotification + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from( + value: IceSelectedTupleChangeNotificationRef<'a>, + ) -> ::planus::Result { + ::core::result::Result::Ok(Self { + tuple: ::planus::alloc::boxed::Box::new( + ::core::convert::TryInto::try_into(value.tuple()?)?, + ), + }) + } + } + + impl<'a> ::planus::TableRead<'a> for IceSelectedTupleChangeNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for IceSelectedTupleChangeNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[IceSelectedTupleChangeNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for IceSelectedTupleChangeNotification + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for IceSelectedTupleChangeNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[IceSelectedTupleChangeNotificationRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum IceState { + New = 0, + Connected = 1, + Completed = 2, + Disconnected = 3, + Closed = 4, + } + + impl ::core::convert::TryFrom for IceState { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 0 => ::core::result::Result::Ok(IceState::New), + 1 => ::core::result::Result::Ok(IceState::Connected), + 2 => ::core::result::Result::Ok(IceState::Completed), + 3 => ::core::result::Result::Ok(IceState::Disconnected), + 4 => ::core::result::Result::Ok(IceState::Closed), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: IceState) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for IceState { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for IceState { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for IceState { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> IceState { + *self + } + } + + impl ::planus::WriteAsDefault for IceState { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &IceState, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for IceState { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for IceState { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for IceState { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "IceState", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for IceState { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + + #[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + #[repr(u8)] + pub enum DtlsState { + New = 0, + Connecting = 1, + Connected = 2, + Failed = 3, + Closed = 4, + } + + impl ::core::convert::TryFrom for DtlsState { + type Error = ::planus::errors::UnknownEnumTagKind; + fn try_from( + value: u8, + ) -> ::core::result::Result + { + #[allow(clippy::match_single_binding)] + match value { + 0 => ::core::result::Result::Ok(DtlsState::New), + 1 => ::core::result::Result::Ok(DtlsState::Connecting), + 2 => ::core::result::Result::Ok(DtlsState::Connected), + 3 => ::core::result::Result::Ok(DtlsState::Failed), + 4 => ::core::result::Result::Ok(DtlsState::Closed), + + _ => ::core::result::Result::Err(::planus::errors::UnknownEnumTagKind { + tag: value as i128, + }), + } + } + } + + impl ::core::convert::From for u8 { + fn from(value: DtlsState) -> Self { + value as u8 + } + } + + impl ::planus::Primitive for DtlsState { + const ALIGNMENT: usize = 1; + const SIZE: usize = 1; + } + + impl ::planus::WriteAsPrimitive for DtlsState { + #[inline] + fn write( + &self, + cursor: ::planus::Cursor<'_, N>, + buffer_position: u32, + ) { + (*self as u8).write(cursor, buffer_position); + } + } + + impl ::planus::WriteAs for DtlsState { + type Prepared = Self; + + #[inline] + fn prepare(&self, _builder: &mut ::planus::Builder) -> DtlsState { + *self + } + } + + impl ::planus::WriteAsDefault for DtlsState { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + default: &DtlsState, + ) -> ::core::option::Option { + if self == default { + ::core::option::Option::None + } else { + ::core::option::Option::Some(*self) + } + } + } + + impl ::planus::WriteAsOptional for DtlsState { + type Prepared = Self; + + #[inline] + fn prepare( + &self, + _builder: &mut ::planus::Builder, + ) -> ::core::option::Option { + ::core::option::Option::Some(*self) + } + } + + impl<'buf> ::planus::TableRead<'buf> for DtlsState { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result { + let n: u8 = ::planus::TableRead::from_buffer(buffer, offset)?; + ::core::result::Result::Ok(::core::convert::TryInto::try_into(n)?) + } + } + + impl<'buf> ::planus::VectorReadInner<'buf> for DtlsState { + type Error = ::planus::errors::UnknownEnumTag; + const STRIDE: usize = 1; + #[inline] + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'buf>, + offset: usize, + ) -> ::core::result::Result + { + let value = ::from_buffer(buffer, offset); + let value: ::core::result::Result = + ::core::convert::TryInto::try_into(value); + value.map_err(|error_kind| { + error_kind.with_error_location( + "DtlsState", + "VectorRead::from_buffer", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite for DtlsState { + const STRIDE: usize = 1; + + type Value = Self; + + fn prepare(&self, _builder: &mut ::planus::Builder) -> Self { + *self + } + + #[inline] + unsafe fn write_values( + values: &[Self], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 1]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - i as u32, + ); + } + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct IceStateChangeNotification { + pub ice_state: self::IceState, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for IceStateChangeNotification { + fn default() -> Self { + Self { + ice_state: self::IceState::New, + } + } + } + + impl IceStateChangeNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_ice_state: impl ::planus::WriteAsDefault, + ) -> ::planus::Offset { + let prepared_ice_state = field_ice_state.prepare(builder, &self::IceState::New); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 1>::new(builder); + + if prepared_ice_state.is_some() { + table_writer.calculate_size::(2); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_ice_state) = prepared_ice_state + { + table_writer.write::<_, _, 1>(0, &prepared_ice_state); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for IceStateChangeNotification + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for IceStateChangeNotification + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for IceStateChangeNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + IceStateChangeNotification::create(builder, &self.ice_state) + } + } + + #[derive(Copy, Clone)] + pub struct IceStateChangeNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> IceStateChangeNotificationRef<'a> { + pub fn ice_state(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "IceStateChangeNotification", "ice_state")? + .unwrap_or(self::IceState::New), + ) + } + } + + impl<'a> ::core::fmt::Debug for IceStateChangeNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("IceStateChangeNotificationRef"); + f.field("ice_state", &self.ice_state()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for IceStateChangeNotification + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: IceStateChangeNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + ice_state: ::core::convert::TryInto::try_into(value.ice_state()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for IceStateChangeNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for IceStateChangeNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[IceStateChangeNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for IceStateChangeNotification + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for IceStateChangeNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[IceStateChangeNotificationRef]", + "read_as_root", + 0, + ) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct DtlsStateChangeNotification { + pub dtls_state: self::DtlsState, + pub remote_cert: ::core::option::Option<::planus::alloc::string::String>, + } + + #[allow(clippy::derivable_impls)] + impl ::core::default::Default for DtlsStateChangeNotification { + fn default() -> Self { + Self { + dtls_state: self::DtlsState::New, + remote_cert: ::core::default::Default::default(), + } + } + } + + impl DtlsStateChangeNotification { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_dtls_state: impl ::planus::WriteAsDefault, + field_remote_cert: impl ::planus::WriteAsOptional< + ::planus::Offset<::core::primitive::str>, + >, + ) -> ::planus::Offset { + let prepared_dtls_state = + field_dtls_state.prepare(builder, &self::DtlsState::New); + + let prepared_remote_cert = field_remote_cert.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<6, 5>::new(builder); + + if prepared_dtls_state.is_some() { + table_writer.calculate_size::(2); + } + if prepared_remote_cert.is_some() { + table_writer.calculate_size::<::planus::Offset>(4); + } + + table_writer.finish_calculating(); + + unsafe { + if let ::core::option::Option::Some(prepared_remote_cert) = + prepared_remote_cert + { + table_writer.write::<_, _, 4>(1, &prepared_remote_cert); + } + if let ::core::option::Option::Some(prepared_dtls_state) = + prepared_dtls_state + { + table_writer.write::<_, _, 1>(0, &prepared_dtls_state); + } + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> + for DtlsStateChangeNotification + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> + for DtlsStateChangeNotification + { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for DtlsStateChangeNotification { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + DtlsStateChangeNotification::create( + builder, + &self.dtls_state, + &self.remote_cert, + ) + } + } + + #[derive(Copy, Clone)] + pub struct DtlsStateChangeNotificationRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> DtlsStateChangeNotificationRef<'a> { + pub fn dtls_state(&self) -> ::planus::Result { + ::core::result::Result::Ok( + self.0 + .access(0, "DtlsStateChangeNotification", "dtls_state")? + .unwrap_or(self::DtlsState::New), + ) + } + + pub fn remote_cert( + &self, + ) -> ::planus::Result<::core::option::Option<&'a ::core::primitive::str>> + { + self.0 + .access(1, "DtlsStateChangeNotification", "remote_cert") + } + } + + impl<'a> ::core::fmt::Debug for DtlsStateChangeNotificationRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("DtlsStateChangeNotificationRef"); + f.field("dtls_state", &self.dtls_state()); + if let ::core::option::Option::Some(field_remote_cert) = + self.remote_cert().transpose() + { + f.field("remote_cert", &field_remote_cert); + } + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> + for DtlsStateChangeNotification + { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: DtlsStateChangeNotificationRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + dtls_state: ::core::convert::TryInto::try_into(value.dtls_state()?)?, + remote_cert: if let ::core::option::Option::Some(remote_cert) = + value.remote_cert()? + { + ::core::option::Option::Some(::core::convert::TryInto::try_into( + remote_cert, + )?) + } else { + ::core::option::Option::None + }, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for DtlsStateChangeNotificationRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for DtlsStateChangeNotificationRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[DtlsStateChangeNotificationRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> + for DtlsStateChangeNotification + { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for DtlsStateChangeNotificationRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[DtlsStateChangeNotificationRef]", + "read_as_root", + 0, + ) + }) + } + } + } + pub mod rtp_observer { + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct AddProducerRequest { + pub producer_id: ::planus::alloc::string::String, + } + + impl AddProducerRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_producer_id: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_producer_id = field_producer_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_producer_id); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for AddProducerRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for AddProducerRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for AddProducerRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + AddProducerRequest::create(builder, &self.producer_id) + } + } + + #[derive(Copy, Clone)] + pub struct AddProducerRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> AddProducerRequestRef<'a> { + pub fn producer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "AddProducerRequest", "producer_id") + } + } + + impl<'a> ::core::fmt::Debug for AddProducerRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("AddProducerRequestRef"); + f.field("producer_id", &self.producer_id()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for AddProducerRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: AddProducerRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + producer_id: ::core::convert::TryInto::try_into(value.producer_id()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for AddProducerRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for AddProducerRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[AddProducerRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for AddProducerRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for AddProducerRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location("[AddProducerRequestRef]", "read_as_root", 0) + }) + } + } + + #[derive( + Clone, + Debug, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + ::serde::Serialize, + ::serde::Deserialize, + )] + pub struct RemoveProducerRequest { + pub producer_id: ::planus::alloc::string::String, + } + + impl RemoveProducerRequest { + #[allow(clippy::too_many_arguments)] + pub fn create( + builder: &mut ::planus::Builder, + field_producer_id: impl ::planus::WriteAs<::planus::Offset>, + ) -> ::planus::Offset { + let prepared_producer_id = field_producer_id.prepare(builder); + + let mut table_writer = + ::planus::table_writer::TableWriter::<4, 4>::new(builder); + + table_writer.calculate_size::<::planus::Offset>(2); + + table_writer.finish_calculating(); + + unsafe { + table_writer.write::<_, _, 4>(0, &prepared_producer_id); + } + + table_writer.finish() + } + } + + impl ::planus::WriteAs<::planus::Offset> for RemoveProducerRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + ::planus::WriteAsOffset::prepare(self, builder) + } + } + + impl ::planus::WriteAsOptional<::planus::Offset> for RemoveProducerRequest { + type Prepared = ::planus::Offset; + + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::core::option::Option<::planus::Offset> + { + ::core::option::Option::Some(::planus::WriteAsOffset::prepare(self, builder)) + } + } + + impl ::planus::WriteAsOffset for RemoveProducerRequest { + fn prepare( + &self, + builder: &mut ::planus::Builder, + ) -> ::planus::Offset { + RemoveProducerRequest::create(builder, &self.producer_id) + } + } + + #[derive(Copy, Clone)] + pub struct RemoveProducerRequestRef<'a>(::planus::table_reader::Table<'a>); + + impl<'a> RemoveProducerRequestRef<'a> { + pub fn producer_id(&self) -> ::planus::Result<&'a ::core::primitive::str> { + self.0 + .access_required(0, "RemoveProducerRequest", "producer_id") + } + } + + impl<'a> ::core::fmt::Debug for RemoveProducerRequestRef<'a> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut f = f.debug_struct("RemoveProducerRequestRef"); + f.field("producer_id", &self.producer_id()); + f.finish() + } + } + + impl<'a> ::core::convert::TryFrom> for RemoveProducerRequest { + type Error = ::planus::Error; + + #[allow(unreachable_code)] + fn try_from(value: RemoveProducerRequestRef<'a>) -> ::planus::Result { + ::core::result::Result::Ok(Self { + producer_id: ::core::convert::TryInto::try_into(value.producer_id()?)?, + }) + } + } + + impl<'a> ::planus::TableRead<'a> for RemoveProducerRequestRef<'a> { + fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self(::planus::table_reader::Table::from_buffer( + buffer, offset, + )?)) + } + } + + impl<'a> ::planus::VectorReadInner<'a> for RemoveProducerRequestRef<'a> { + type Error = ::planus::Error; + const STRIDE: usize = 4; + + unsafe fn from_buffer( + buffer: ::planus::SliceWithStartOffset<'a>, + offset: usize, + ) -> ::planus::Result { + ::planus::TableRead::from_buffer(buffer, offset).map_err(|error_kind| { + error_kind.with_error_location( + "[RemoveProducerRequestRef]", + "get", + buffer.offset_from_start, + ) + }) + } + } + + impl ::planus::VectorWrite<::planus::Offset> for RemoveProducerRequest { + type Value = ::planus::Offset; + const STRIDE: usize = 4; + fn prepare(&self, builder: &mut ::planus::Builder) -> Self::Value { + ::planus::WriteAs::prepare(self, builder) + } + + #[inline] + unsafe fn write_values( + values: &[::planus::Offset], + bytes: *mut ::core::mem::MaybeUninit, + buffer_position: u32, + ) { + let bytes = bytes as *mut [::core::mem::MaybeUninit; 4]; + for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) { + ::planus::WriteAsPrimitive::write( + v, + ::planus::Cursor::new(&mut *bytes.add(i)), + buffer_position - (Self::STRIDE * i) as u32, + ); + } + } + } + + impl<'a> ::planus::ReadAsRoot<'a> for RemoveProducerRequestRef<'a> { + fn read_as_root(slice: &'a [u8]) -> ::planus::Result { + ::planus::TableRead::from_buffer( + ::planus::SliceWithStartOffset { + buffer: slice, + offset_from_start: 0, + }, + 0, + ) + .map_err(|error_kind| { + error_kind.with_error_location( + "[RemoveProducerRequestRef]", + "read_as_root", + 0, + ) + }) + } + } + } + } +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 7d62f481ed..c55b6f2b8f 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -49,6 +49,7 @@ //! and are a good place to start until we have demo apps built in Rust). pub mod data_structures; +pub mod fbs; mod macros; mod messages; #[doc(hidden)] diff --git a/rust/src/messages.rs b/rust/src/messages.rs index 865954b592..e09f22b5af 100644 --- a/rust/src/messages.rs +++ b/rust/src/messages.rs @@ -25,7 +25,7 @@ use crate::srtp_parameters::{SrtpCryptoSuite, SrtpParameters}; use crate::transport::{TransportId, TransportTraceEventType}; use crate::webrtc_server::{WebRtcServerDump, WebRtcServerId, WebRtcServerListenInfos}; use crate::webrtc_transport::{TransportListenIps, WebRtcTransportListen, WebRtcTransportOptions}; -use crate::worker::{WorkerDump, WorkerUpdateSettings}; +use crate::worker::WorkerDump; use parking_lot::Mutex; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; @@ -158,15 +158,6 @@ request_response!( WorkerDump ); -request_response!( - &'static str, - "worker.updateSettings", - WorkerUpdateSettingsRequest { - #[serde(flatten)] - data: WorkerUpdateSettings, - }, -); - request_response!( &'static str, "worker.createWebRtcServer", @@ -195,14 +186,6 @@ request_response!( WebRtcServerDump, ); -request_response!( - &'static str, - "worker.createRouter", - WorkerCreateRouterRequest { - router_id: RouterId, - }, -); - request_response!( &'static str, "worker.closeRouter", diff --git a/rust/src/router.rs b/rust/src/router.rs index 4ee29355da..bca8accb7e 100644 --- a/rust/src/router.rs +++ b/rust/src/router.rs @@ -51,7 +51,7 @@ use crate::transport::{ TransportId, }; use crate::webrtc_transport::{WebRtcTransport, WebRtcTransportListen, WebRtcTransportOptions}; -use crate::worker::{Channel, PayloadChannel, RequestError, Worker}; +use crate::worker::{Channel, RequestError, Worker}; use crate::{ortc, uuid_based_wrapper_type}; use async_executor::Executor; use async_lock::Mutex as AsyncMutex; @@ -367,7 +367,6 @@ struct Inner { executor: Arc>, rtp_capabilities: RtpCapabilitiesFinalized, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, app_data: AppData, producers: Arc>>, @@ -441,7 +440,6 @@ impl Router { id: RouterId, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, rtp_capabilities: RtpCapabilitiesFinalized, app_data: AppData, worker: Worker, @@ -473,7 +471,6 @@ impl Router { executor, rtp_capabilities, channel, - payload_channel, handlers, producers, data_producers, @@ -576,7 +573,6 @@ impl Router { transport_id, Arc::clone(&self.inner.executor), self.inner.channel.clone(), - self.inner.payload_channel.clone(), direct_transport_options.app_data, self.clone(), ); @@ -637,7 +633,6 @@ impl Router { transport_id, Arc::clone(&self.inner.executor), self.inner.channel.clone(), - self.inner.payload_channel.clone(), data, webrtc_transport_options.app_data, self.clone(), @@ -703,7 +698,6 @@ impl Router { transport_id, Arc::clone(&self.inner.executor), self.inner.channel.clone(), - self.inner.payload_channel.clone(), data, pipe_transport_options.app_data, self.clone(), @@ -765,7 +759,6 @@ impl Router { transport_id, Arc::clone(&self.inner.executor), self.inner.channel.clone(), - self.inner.payload_channel.clone(), data, plain_transport_options.app_data, self.clone(), diff --git a/rust/src/router/consumer.rs b/rust/src/router/consumer.rs index 7cc9e6b223..fc45857d80 100644 --- a/rust/src/router/consumer.rs +++ b/rust/src/router/consumer.rs @@ -12,7 +12,7 @@ use crate::rtp_parameters::{MediaKind, MimeType, RtpCapabilities, RtpParameters} use crate::scalability_modes::ScalabilityMode; use crate::transport::Transport; use crate::uuid_based_wrapper_type; -use crate::worker::{Channel, PayloadChannel, RequestError, SubscriptionHandler}; +use crate::worker::{Channel, RequestError, SubscriptionHandler}; use async_executor::Executor; use event_listener_primitives::{Bag, BagOnce, HandlerId}; use log::{debug, error}; @@ -341,17 +341,13 @@ enum Notification { ProducerClose, ProducerPause, ProducerResume, + // TODO. + // Rtp, Score(ConsumerScore), LayersChange(Option), Trace(ConsumerTraceEventData), } -#[derive(Debug, Deserialize)] -#[serde(tag = "event", rename_all = "lowercase", content = "data")] -enum PayloadNotification { - Rtp, -} - #[derive(Default)] #[allow(clippy::type_complexity)] struct Handlers { @@ -468,7 +464,6 @@ impl Consumer { paused: bool, executor: Arc>, channel: Channel, - payload_channel: &PayloadChannel, producer_paused: bool, score: ConsumerScore, preferred_layers: Option, @@ -541,6 +536,14 @@ impl Consumer { handlers.resume.call_simple(); } } + /* + * TODO. + Notification::Rtp => { + handlers.rtp.call(|callback| { + callback(notification); + }); + } + */ Notification::Score(consumer_score) => { *score.lock() = consumer_score.clone(); handlers.score.call_simple(&consumer_score); @@ -560,25 +563,6 @@ impl Consumer { }) }; - let payload_subscription_handler = { - let handlers = Arc::clone(&handlers); - - payload_channel.subscribe_to_notifications(id.into(), move |message, payload| { - match serde_json::from_slice::(message) { - Ok(notification) => match notification { - PayloadNotification::Rtp => { - handlers.rtp.call(|callback| { - callback(payload); - }); - } - }, - Err(error) => { - error!("Failed to parse payload notification: {}", error); - } - } - }) - }; - let on_transport_close_handler = transport.on_close({ let inner_weak = Arc::clone(&inner_weak); @@ -609,10 +593,7 @@ impl Consumer { transport, weak_producer: producer.downgrade(), closed, - _subscription_handlers: Mutex::new(vec![ - subscription_handler, - payload_subscription_handler, - ]), + _subscription_handlers: Mutex::new(vec![subscription_handler]), _on_transport_close_handler: Mutex::new(on_transport_close_handler), }); diff --git a/rust/src/router/data_consumer.rs b/rust/src/router/data_consumer.rs index 5477e31400..73d8f0da8e 100644 --- a/rust/src/router/data_consumer.rs +++ b/rust/src/router/data_consumer.rs @@ -11,13 +11,14 @@ use crate::messages::{ use crate::sctp_parameters::SctpStreamParameters; use crate::transport::Transport; use crate::uuid_based_wrapper_type; -use crate::worker::{Channel, PayloadChannel, RequestError, SubscriptionHandler}; +use crate::worker::{Channel, RequestError, SubscriptionHandler}; use async_executor::Executor; use event_listener_primitives::{Bag, BagOnce, HandlerId}; use log::{debug, error}; use parking_lot::Mutex; use serde::{Deserialize, Serialize}; -use std::borrow::Cow; +// TODO. +// use std::borrow::Cow; use std::fmt; use std::fmt::Debug; use std::sync::atomic::{AtomicBool, Ordering}; @@ -168,18 +169,14 @@ pub enum DataConsumerType { enum Notification { DataProducerClose, SctpSendBufferFull, + // TODO. + // Message { ppid: u32 }, #[serde(rename_all = "camelCase")] BufferedAmountLow { buffered_amount: u32, }, } -#[derive(Debug, Deserialize)] -#[serde(tag = "event", rename_all = "lowercase", content = "data")] -enum PayloadNotification { - Message { ppid: u32 }, -} - #[derive(Default)] #[allow(clippy::type_complexity)] struct Handlers { @@ -201,7 +198,6 @@ struct Inner { direct: bool, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, app_data: AppData, transport: Arc, @@ -345,7 +341,6 @@ impl DataConsumer { data_producer: DataProducer, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, app_data: AppData, transport: Arc, direct: bool, @@ -386,30 +381,13 @@ impl DataConsumer { Notification::SctpSendBufferFull => { handlers.sctp_send_buffer_full.call_simple(); } - Notification::BufferedAmountLow { buffered_amount } => { - handlers.buffered_amount_low.call(|callback| { - callback(buffered_amount); - }); - } - }, - Err(error) => { - error!("Failed to parse notification: {}", error); - } - } - }) - }; - - let payload_subscription_handler = { - let handlers = Arc::clone(&handlers); - - payload_channel.subscribe_to_notifications(id.into(), move |message, payload| { - match serde_json::from_slice::(message) { - Ok(notification) => match notification { - PayloadNotification::Message { ppid } => { - match WebRtcMessage::new(ppid, Cow::from(payload)) { + /* + * TODO. + Notification::Message { ppid } => { + match WebRtcMessage::new(ppid, Cow::from(_notification)) { Ok(message) => { handlers.message.call(|callback| { - callback(&message); + callback(&_notification); }); } Err(ppid) => { @@ -417,9 +395,15 @@ impl DataConsumer { } } } + */ + Notification::BufferedAmountLow { buffered_amount } => { + handlers.buffered_amount_low.call(|callback| { + callback(buffered_amount); + }); + } }, Err(error) => { - error!("Failed to parse payload notification: {}", error); + error!("Failed to parse notification: {}", error); } } }) @@ -446,16 +430,12 @@ impl DataConsumer { direct, executor, channel, - payload_channel, handlers, app_data, transport, weak_data_producer: data_producer.downgrade(), closed, - _subscription_handlers: Mutex::new(vec![ - subscription_handler, - payload_subscription_handler, - ]), + _subscription_handlers: Mutex::new(vec![subscription_handler]), _on_transport_close_handler: Mutex::new(on_transport_close_handler), }); @@ -667,18 +647,15 @@ impl DataConsumer { } } +// TODO: used because 'payload' is not being used yet. impl DirectDataConsumer { /// Sends direct messages from the Rust process. pub async fn send(&self, message: WebRtcMessage<'_>) -> Result<(), RequestError> { - let (ppid, payload) = message.into_ppid_and_payload(); + let (ppid, _payload) = message.into_ppid_and_payload(); self.inner - .payload_channel - .request( - self.inner.id, - DataConsumerSendRequest { ppid }, - payload.into_owned(), - ) + .channel + .request(self.inner.id, DataConsumerSendRequest { ppid }) .await } } diff --git a/rust/src/router/data_producer.rs b/rust/src/router/data_producer.rs index 64e9f2ad55..8a5daa0398 100644 --- a/rust/src/router/data_producer.rs +++ b/rust/src/router/data_producer.rs @@ -9,7 +9,7 @@ use crate::messages::{ use crate::sctp_parameters::SctpStreamParameters; use crate::transport::Transport; use crate::uuid_based_wrapper_type; -use crate::worker::{Channel, NotificationError, PayloadChannel, RequestError}; +use crate::worker::{Channel, NotificationError, RequestError}; use async_executor::Executor; use event_listener_primitives::{BagOnce, HandlerId}; use log::{debug, error}; @@ -137,7 +137,6 @@ struct Inner { direct: bool, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, app_data: AppData, transport: Arc, @@ -269,7 +268,6 @@ impl DataProducer { protocol: String, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, app_data: AppData, transport: Arc, direct: bool, @@ -299,7 +297,6 @@ impl DataProducer { direct, executor, channel, - payload_channel, handlers, app_data, transport, @@ -431,12 +428,12 @@ impl DataProducer { impl DirectDataProducer { /// Sends direct messages from the Rust to the worker. pub fn send(&self, message: WebRtcMessage<'_>) -> Result<(), NotificationError> { - let (ppid, payload) = message.into_ppid_and_payload(); + let (ppid, _payload) = message.into_ppid_and_payload(); - self.inner.payload_channel.notify( + self.inner.channel.notify( self.inner.id, DataProducerSendNotification { ppid }, - payload.into_owned(), + // payload.into_owned(), ) } } diff --git a/rust/src/router/direct_transport.rs b/rust/src/router/direct_transport.rs index 4658bb0564..87272f8e18 100644 --- a/rust/src/router/direct_transport.rs +++ b/rust/src/router/direct_transport.rs @@ -15,9 +15,7 @@ use crate::transport::{ RtpListener, SctpListener, Transport, TransportGeneric, TransportId, TransportTraceEventData, TransportTraceEventType, }; -use crate::worker::{ - Channel, NotificationError, PayloadChannel, RequestError, SubscriptionHandler, -}; +use crate::worker::{Channel, NotificationError, RequestError, SubscriptionHandler}; use async_executor::Executor; use async_trait::async_trait; use event_listener_primitives::{Bag, BagOnce, HandlerId}; @@ -126,12 +124,8 @@ struct Handlers { #[serde(tag = "event", rename_all = "lowercase", content = "data")] enum Notification { Trace(TransportTraceEventData), -} - -#[derive(Debug, Deserialize)] -#[serde(tag = "event", rename_all = "lowercase", content = "data")] -enum PayloadNotification { - Rtcp, + // TODO. + // Rtcp, } struct Inner { @@ -141,7 +135,6 @@ struct Inner { cname_for_producers: Mutex>, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, app_data: AppData, // Make sure router is not dropped until this transport is not dropped @@ -401,10 +394,6 @@ impl TransportImpl for DirectTransport { &self.inner.channel } - fn payload_channel(&self) -> &PayloadChannel { - &self.inner.payload_channel - } - fn executor(&self) -> &Arc> { &self.inner.executor } @@ -427,7 +416,6 @@ impl DirectTransport { id: TransportId, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, app_data: AppData, router: Router, ) -> Self { @@ -443,7 +431,14 @@ impl DirectTransport { Ok(notification) => match notification { Notification::Trace(trace_event_data) => { handlers.trace.call_simple(&trace_event_data); - } + } /* + * TODO. + Notification::Rtcp => { + handlers.rtcp.call(|callback| { + callback(notification); + }); + } + */ }, Err(error) => { error!("Failed to parse notification: {}", error); @@ -452,25 +447,6 @@ impl DirectTransport { }) }; - let payload_subscription_handler = { - let handlers = Arc::clone(&handlers); - - payload_channel.subscribe_to_notifications(id.into(), move |message, payload| { - match serde_json::from_slice::(message) { - Ok(notification) => match notification { - PayloadNotification::Rtcp => { - handlers.rtcp.call(|callback| { - callback(payload); - }); - } - }, - Err(error) => { - error!("Failed to parse payload notification: {}", error); - } - } - }) - }; - let next_mid_for_consumers = AtomicUsize::default(); let used_sctp_stream_ids = Mutex::new(IntMap::default()); let cname_for_producers = Mutex::new(None); @@ -493,15 +469,11 @@ impl DirectTransport { cname_for_producers, executor, channel, - payload_channel, handlers, app_data, router, closed: AtomicBool::new(false), - _subscription_handlers: Mutex::new(vec![ - subscription_handler, - payload_subscription_handler, - ]), + _subscription_handlers: Mutex::new(vec![subscription_handler]), _on_router_close_handler: Mutex::new(on_router_close_handler), }); @@ -513,10 +485,10 @@ impl DirectTransport { /// Send a RTCP packet from the Rust process. /// /// * `rtcp_packet` - Bytes containing a valid RTCP packet (can be a compound packet). - pub fn send_rtcp(&self, rtcp_packet: Vec) -> Result<(), NotificationError> { + pub fn send_rtcp(&self, _rtcp_packet: Vec) -> Result<(), NotificationError> { self.inner - .payload_channel - .notify(self.id(), TransportSendRtcpNotification {}, rtcp_packet) + .channel + .notify(self.id(), TransportSendRtcpNotification {}) } /// Callback is called when the direct transport receives a RTCP packet from its router. diff --git a/rust/src/router/pipe_transport.rs b/rust/src/router/pipe_transport.rs index 187811d494..cb064463bc 100644 --- a/rust/src/router/pipe_transport.rs +++ b/rust/src/router/pipe_transport.rs @@ -16,7 +16,7 @@ use crate::transport::{ RtpListener, SctpListener, Transport, TransportGeneric, TransportId, TransportTraceEventData, TransportTraceEventType, }; -use crate::worker::{Channel, PayloadChannel, RequestError, SubscriptionHandler}; +use crate::worker::{Channel, RequestError, SubscriptionHandler}; use async_executor::Executor; use async_trait::async_trait; use event_listener_primitives::{Bag, BagOnce, HandlerId}; @@ -188,7 +188,6 @@ struct Inner { cname_for_producers: Mutex>, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, data: Arc, app_data: AppData, @@ -437,10 +436,6 @@ impl TransportImpl for PipeTransport { &self.inner.channel } - fn payload_channel(&self) -> &PayloadChannel { - &self.inner.payload_channel - } - fn executor(&self) -> &Arc> { &self.inner.executor } @@ -463,7 +458,6 @@ impl PipeTransport { id: TransportId, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, data: PipeTransportData, app_data: AppData, router: Router, @@ -528,7 +522,6 @@ impl PipeTransport { cname_for_producers, executor, channel, - payload_channel, handlers, data, app_data, diff --git a/rust/src/router/plain_transport.rs b/rust/src/router/plain_transport.rs index ee15cb195d..c806751d50 100644 --- a/rust/src/router/plain_transport.rs +++ b/rust/src/router/plain_transport.rs @@ -16,7 +16,7 @@ use crate::transport::{ RtpListener, SctpListener, Transport, TransportGeneric, TransportId, TransportTraceEventData, TransportTraceEventType, }; -use crate::worker::{Channel, PayloadChannel, RequestError, SubscriptionHandler}; +use crate::worker::{Channel, RequestError, SubscriptionHandler}; use async_executor::Executor; use async_trait::async_trait; use event_listener_primitives::{Bag, BagOnce, HandlerId}; @@ -225,7 +225,6 @@ struct Inner { cname_for_producers: Mutex>, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, data: Arc, app_data: AppData, @@ -467,10 +466,6 @@ impl TransportImpl for PlainTransport { &self.inner.channel } - fn payload_channel(&self) -> &PayloadChannel { - &self.inner.payload_channel - } - fn executor(&self) -> &Arc> { &self.inner.executor } @@ -493,7 +488,6 @@ impl PlainTransport { id: TransportId, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, data: PlainTransportData, app_data: AppData, router: Router, @@ -568,7 +562,6 @@ impl PlainTransport { cname_for_producers, executor, channel, - payload_channel, handlers, data, app_data, diff --git a/rust/src/router/producer.rs b/rust/src/router/producer.rs index 17549fd822..3ee856b797 100644 --- a/rust/src/router/producer.rs +++ b/rust/src/router/producer.rs @@ -11,9 +11,7 @@ pub use crate::ortc::RtpMapping; use crate::rtp_parameters::{MediaKind, MimeType, RtpParameters}; use crate::transport::Transport; use crate::uuid_based_wrapper_type; -use crate::worker::{ - Channel, NotificationError, PayloadChannel, RequestError, SubscriptionHandler, -}; +use crate::worker::{Channel, NotificationError, RequestError, SubscriptionHandler}; use async_executor::Executor; use event_listener_primitives::{Bag, BagOnce, HandlerId}; use hash_hasher::HashedMap; @@ -299,7 +297,6 @@ struct Inner { score: Arc>>, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, app_data: AppData, transport: Arc, @@ -441,7 +438,6 @@ impl Producer { paused: bool, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, app_data: AppData, transport: Arc, direct: bool, @@ -503,7 +499,6 @@ impl Producer { score, executor, channel, - payload_channel, handlers, app_data, transport, @@ -745,10 +740,10 @@ impl Producer { impl DirectProducer { /// Sends a RTP packet from the Rust process. - pub fn send(&self, rtp_packet: Vec) -> Result<(), NotificationError> { + pub fn send(&self, _rtp_packet: Vec) -> Result<(), NotificationError> { self.inner - .payload_channel - .notify(self.inner.id, ProducerSendNotification {}, rtp_packet) + .channel + .notify(self.inner.id, ProducerSendNotification {}) } } diff --git a/rust/src/router/transport.rs b/rust/src/router/transport.rs index 5e7eca730b..d15771596e 100644 --- a/rust/src/router/transport.rs +++ b/rust/src/router/transport.rs @@ -15,7 +15,7 @@ use crate::producer::{Producer, ProducerId, ProducerOptions}; use crate::router::Router; use crate::rtp_parameters::{MediaKind, RtpEncodingParameters}; use crate::sctp_parameters::SctpStreamParameters; -use crate::worker::{Channel, PayloadChannel, RequestError}; +use crate::worker::{Channel, RequestError}; use crate::{ortc, uuid_based_wrapper_type}; use async_executor::Executor; use async_trait::async_trait; @@ -333,8 +333,6 @@ pub enum ConsumeDataError { pub(super) trait TransportImpl: TransportGeneric { fn channel(&self) -> &Channel; - fn payload_channel(&self) -> &PayloadChannel; - fn executor(&self) -> &Arc>; fn next_mid_for_consumers(&self) -> &AtomicUsize; @@ -493,7 +491,6 @@ pub(super) trait TransportImpl: TransportGeneric { paused, Arc::clone(self.executor()), self.channel().clone(), - self.payload_channel().clone(), app_data, Arc::new(self.clone()), transport_type == TransportType::Direct, @@ -597,7 +594,6 @@ pub(super) trait TransportImpl: TransportGeneric { response.paused, Arc::clone(self.executor()), self.channel().clone(), - self.payload_channel(), response.producer_paused, response.score, response.preferred_layers, @@ -668,7 +664,6 @@ pub(super) trait TransportImpl: TransportGeneric { response.protocol, Arc::clone(self.executor()), self.channel().clone(), - self.payload_channel().clone(), app_data, Arc::new(self.clone()), transport_type == TransportType::Direct, @@ -764,7 +759,6 @@ pub(super) trait TransportImpl: TransportGeneric { data_producer, Arc::clone(self.executor()), self.channel().clone(), - self.payload_channel().clone(), app_data, Arc::new(self.clone()), transport_type == TransportType::Direct, diff --git a/rust/src/router/webrtc_transport.rs b/rust/src/router/webrtc_transport.rs index 53a1ac08ca..c2604ff519 100644 --- a/rust/src/router/webrtc_transport.rs +++ b/rust/src/router/webrtc_transport.rs @@ -22,7 +22,7 @@ use crate::transport::{ TransportTraceEventType, }; use crate::webrtc_server::WebRtcServer; -use crate::worker::{Channel, PayloadChannel, RequestError, SubscriptionHandler}; +use crate::worker::{Channel, RequestError, SubscriptionHandler}; use async_executor::Executor; use async_trait::async_trait; use event_listener_primitives::{Bag, BagOnce, HandlerId}; @@ -312,7 +312,6 @@ struct Inner { cname_for_producers: Mutex>, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, handlers: Arc, data: Arc, app_data: AppData, @@ -565,10 +564,6 @@ impl TransportImpl for WebRtcTransport { &self.inner.channel } - fn payload_channel(&self) -> &PayloadChannel { - &self.inner.payload_channel - } - fn executor(&self) -> &Arc> { &self.inner.executor } @@ -592,7 +587,6 @@ impl WebRtcTransport { id: TransportId, executor: Arc>, channel: Channel, - payload_channel: PayloadChannel, data: WebRtcTransportData, app_data: AppData, router: Router, @@ -697,7 +691,6 @@ impl WebRtcTransport { cname_for_producers, executor, channel, - payload_channel, handlers, data, app_data, diff --git a/rust/src/worker.rs b/rust/src/worker.rs index 431b2a9222..2cbf4cad1c 100644 --- a/rust/src/worker.rs +++ b/rust/src/worker.rs @@ -3,14 +3,11 @@ mod channel; mod common; -mod payload_channel; mod utils; use crate::data_structures::AppData; -use crate::messages::{ - WorkerCloseRequest, WorkerCreateRouterRequest, WorkerCreateWebRtcServerRequest, - WorkerDumpRequest, WorkerUpdateSettingsRequest, -}; +use crate::fbs; +use crate::messages::{WorkerCreateWebRtcServerRequest, WorkerDumpRequest}; pub use crate::ortc::RtpCapabilitiesError; use crate::router::{Router, RouterId, RouterOptions}; use crate::webrtc_server::{WebRtcServer, WebRtcServerId, WebRtcServerOptions}; @@ -19,13 +16,13 @@ pub use crate::worker::utils::ExitError; use crate::worker_manager::WorkerManager; use crate::{ortc, uuid_based_wrapper_type}; use async_executor::Executor; -pub(crate) use channel::Channel; +pub(crate) use channel::{Channel, NotificationError}; pub(crate) use common::{SubscriptionHandler, SubscriptionTarget}; use event_listener_primitives::{Bag, BagOnce, HandlerId}; use futures_lite::FutureExt; use log::{debug, error, warn}; use parking_lot::Mutex; -pub(crate) use payload_channel::{NotificationError, PayloadChannel}; +use planus::Builder; use serde::{Deserialize, Serialize}; use std::ops::RangeInclusive; use std::path::PathBuf; @@ -272,8 +269,7 @@ pub struct WorkerUpdateSettings { #[doc(hidden)] pub struct ChannelMessageHandlers { pub channel_request_handlers: Vec, - pub payload_channel_request_handlers: Vec, - pub payload_channel_notification_handlers: Vec, + pub channel_notification_handlers: Vec, } #[derive(Debug, Clone, Deserialize, Serialize)] @@ -320,7 +316,6 @@ struct Handlers { struct Inner { id: WorkerId, channel: Channel, - payload_channel: PayloadChannel, executor: Arc>, handlers: Handlers, app_data: AppData, @@ -406,7 +401,6 @@ impl Inner { let (mut status_sender, status_receiver) = async_oneshot::oneshot(); let WorkerRunResult { channel, - payload_channel, buffer_worker_messages_guard, } = utils::run_worker_with_channels( id, @@ -424,7 +418,6 @@ impl Inner { let mut inner = Self { id, channel, - payload_channel, executor, handlers, app_data, @@ -489,21 +482,20 @@ impl Inner { let (sender, receiver) = async_oneshot::oneshot(); let id = self.id; let sender = Mutex::new(Some(sender)); - let _handler = self.channel.subscribe_to_notifications( - std::process::id().into(), + let _handler = self.channel.subscribe_to_fbs_notifications( + SubscriptionTarget::String(std::process::id().to_string()), move |notification| { - let result = match serde_json::from_slice(notification) { - Ok(Notification::Running) => { + let result = match notification.event().unwrap() { + fbs::notification::Event::WorkerRunning => { debug!("worker thread running [id:{}]", id); Ok(()) } - Err(error) => Err(io::Error::new( + _ => Err(io::Error::new( io::ErrorKind::Other, - format!( - "unexpected first notification from worker [id:{id}]: {notification:?}; error = {error}" - ), + format!("unexpected first notification from worker [id:{id}]"), )), }; + let _ = sender .lock() .take() @@ -522,7 +514,6 @@ impl Inner { fn setup_message_handling(&mut self) { let channel_receiver = self.channel.get_internal_message_receiver(); - let payload_channel_receiver = self.payload_channel.get_internal_message_receiver(); let id = self.id; let closed = Arc::clone(&self.closed); self.executor @@ -546,20 +537,6 @@ impl Inner { } }) .detach(); - - self.executor - .spawn(async move { - while let Ok(message) = payload_channel_receiver.recv().await { - match message { - payload_channel::InternalMessage::UnexpectedData(data) => error!( - "worker[id:{}] unexpected payload channel data: {}", - id, - String::from_utf8_lossy(&data) - ), - } - } - }) - .detach(); } fn close(&self) { @@ -567,15 +544,17 @@ impl Inner { if !already_closed { let channel = self.channel.clone(); - let payload_channel = self.payload_channel.clone(); + + let builder = Builder::new(); self.executor .spawn(async move { - let _ = channel.request("", WorkerCloseRequest {}).await; + let _ = channel + .request_fbs(builder, "", fbs::request::Method::WorkerClose, None) + .await; // Drop channels in here after response from worker drop(channel); - drop(payload_channel); }) .detach(); @@ -648,10 +627,29 @@ impl Worker { pub async fn update_settings(&self, data: WorkerUpdateSettings) -> Result<(), RequestError> { debug!("update_settings()"); - self.inner + let mut builder = Builder::new(); + let settings = fbs::worker::UpdateSettingsRequest::create( + &mut builder, + data.log_level.unwrap_or_default().as_str(), + data.log_tags + .map(|tags| tags.iter().map(|tag| tag.as_str()).collect::>()), + ); + let body = fbs::request::Body::create_update_settings_request(&mut builder, settings); + + match self + .inner .channel - .request("", WorkerUpdateSettingsRequest { data }) + .request_fbs( + builder, + "", + fbs::request::Method::WorkerUpdateSettings, + Some(body), + ) .await + { + Ok(_) => Ok(()), + Err(error) => Err(error), + } } /// Create a WebRtcServer. @@ -661,7 +659,7 @@ impl Worker { &self, webrtc_server_options: WebRtcServerOptions, ) -> Result { - debug!("create_router()"); + debug!("create_webrtc_server()"); let WebRtcServerOptions { listen_infos, @@ -724,9 +722,18 @@ impl Worker { let _buffer_guard = self.inner.channel.buffer_messages_for(router_id.into()); + let mut builder = Builder::new(); + let data = fbs::worker::CreateRouterRequest::create(&mut builder, router_id.to_string()); + let body = fbs::request::Body::create_create_router_request(&mut builder, data); + self.inner .channel - .request("", WorkerCreateRouterRequest { router_id }) + .request_fbs( + builder, + "", + fbs::request::Method::WorkerCreateRouter, + Some(body), + ) .await .map_err(CreateRouterError::Request)?; @@ -734,7 +741,6 @@ impl Worker { router_id, Arc::clone(&self.inner.executor), self.inner.channel.clone(), - self.inner.payload_channel.clone(), rtp_capabilities, app_data, self.clone(), diff --git a/rust/src/worker/channel.rs b/rust/src/worker/channel.rs index 7219903074..7ccee35b08 100644 --- a/rust/src/worker/channel.rs +++ b/rust/src/worker/channel.rs @@ -1,5 +1,8 @@ -use crate::messages::{Request, WorkerCloseRequest}; -use crate::worker::common::{EventHandlers, SubscriptionTarget, WeakEventHandlers}; +use crate::fbs::{message, notification, request, response}; +use crate::messages::{Notification, Request, WorkerCloseRequest}; +use crate::worker::common::{ + EventHandlers, FBSEventHandlers, FBSWeakEventHandlers, SubscriptionTarget, WeakEventHandlers, +}; use crate::worker::utils; use crate::worker::utils::{PreparedChannelRead, PreparedChannelWrite}; use crate::worker::{RequestError, SubscriptionHandler}; @@ -9,6 +12,7 @@ use log::{debug, error, trace, warn}; use lru::LruCache; use mediasoup_sys::UvAsyncT; use parking_lot::Mutex; +use planus::{Builder, ReadAsRoot, UnionOffset}; use serde::Deserialize; use serde_json::Value; use std::any::TypeId; @@ -17,6 +21,7 @@ use std::fmt::{Debug, Display}; use std::num::NonZeroUsize; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Weak}; +use thiserror::Error; #[derive(Debug, Deserialize)] #[serde(untagged)] @@ -38,11 +43,21 @@ pub(super) enum InternalMessage { Unexpected(Vec), } +#[derive(Debug, Error, Eq, PartialEq)] +pub enum NotificationError { + #[error("Channel already closed")] + ChannelClosed, +} + #[allow(clippy::type_complexity)] pub(crate) struct BufferMessagesGuard { target_id: SubscriptionTarget, buffered_notifications_for: Arc>>>>, + fbs_buffered_notifications_for: Arc>>>>, event_handlers_weak: WeakEventHandlers>, + fbs_event_handlers_weak: FBSWeakEventHandlers< + Arc) + Send + Sync + 'static>, + >, } impl Drop for BufferMessagesGuard { @@ -55,54 +70,54 @@ impl Drop for BufferMessagesGuard { } } } + + let mut fbs_buffered_notifications_for = self.fbs_buffered_notifications_for.lock(); + if let Some(notifications) = fbs_buffered_notifications_for.remove(&self.target_id) { + if let Some(event_handlers) = self.fbs_event_handlers_weak.upgrade() { + for notification in notifications { + let notification = + notification::NotificationRef::read_as_root(¬ification).unwrap(); + event_handlers.call_callbacks_with_single_value(&self.target_id, notification); + } + } + } } } -#[derive(Debug, Deserialize)] -#[serde(untagged)] -enum ChannelReceiveMessage { - #[serde(rename_all = "camelCase")] - Notification { - target_id: SubscriptionTarget, - }, - ResponseSuccess { - id: u32, - // The following field is present, unused, but needed for differentiating successful - // response from error case - #[allow(dead_code)] - accepted: bool, - data: Option, - }, - ResponseError { - id: u32, - // The following field is present, but unused - // error: Value, - reason: String, - }, +#[derive(Debug)] +enum ChannelReceiveMessage<'a> { + Notification(notification::NotificationRef<'a>), + Response(response::ResponseRef<'a>), Event(InternalMessage), } -fn deserialize_message(bytes: &[u8]) -> ChannelReceiveMessage { - match bytes[0] { - // JSON message - b'{' => serde_json::from_slice(bytes).unwrap(), - // Debug log - b'D' => ChannelReceiveMessage::Event(InternalMessage::Debug( - String::from_utf8(Vec::from(&bytes[1..])).unwrap(), - )), - // Warn log - b'W' => ChannelReceiveMessage::Event(InternalMessage::Warn( - String::from_utf8(Vec::from(&bytes[1..])).unwrap(), - )), - // Error log - b'E' => ChannelReceiveMessage::Event(InternalMessage::Error( - String::from_utf8(Vec::from(&bytes[1..])).unwrap(), - )), - // Dump log - b'X' => ChannelReceiveMessage::Event(InternalMessage::Dump( - String::from_utf8(Vec::from(&bytes[1..])).unwrap(), - )), - // Unknown +fn deserialize_message(bytes: &[u8]) -> ChannelReceiveMessage<'_> { + let message_ref = message::MessageRef::read_as_root(&bytes[4..]).unwrap(); + + match message_ref.data().unwrap() { + message::BodyRef::Log(data) => match data.data().unwrap().chars().next() { + // Debug log + Some('D') => ChannelReceiveMessage::Event(InternalMessage::Debug( + String::from_utf8(Vec::from(&data.data().unwrap().as_bytes()[1..])).unwrap(), + )), + // Warn log + Some('W') => ChannelReceiveMessage::Event(InternalMessage::Warn( + String::from_utf8(Vec::from(&data.data().unwrap().as_bytes()[1..])).unwrap(), + )), + // Error log + Some('E') => ChannelReceiveMessage::Event(InternalMessage::Error( + String::from_utf8(Vec::from(&data.data().unwrap().as_bytes()[1..])).unwrap(), + )), + // Dump log + Some('X') => ChannelReceiveMessage::Event(InternalMessage::Dump( + String::from_utf8(Vec::from(&data.data().unwrap().as_bytes()[1..])).unwrap(), + )), + // This should never happen. + _ => ChannelReceiveMessage::Event(InternalMessage::Unexpected(Vec::from(bytes))), + }, + message::BodyRef::Notification(data) => ChannelReceiveMessage::Notification(data), + message::BodyRef::Response(data) => ChannelReceiveMessage::Response(data), + _ => ChannelReceiveMessage::Event(InternalMessage::Unexpected(Vec::from(bytes))), } } @@ -112,6 +127,7 @@ struct ResponseError { } type ResponseResult = Result, ResponseError>; +type FBSResponseResult = Result, ResponseError>; struct RequestDropGuard<'a> { id: u32, @@ -132,6 +148,10 @@ impl<'a> Drop for RequestDropGuard<'a> { if let Some(requests_container) = self.channel.inner.requests_container_weak.upgrade() { requests_container.lock().handlers.remove(&self.id); } + // Remove request handler from the container + if let Some(requests_container) = self.channel.inner.fbs_requests_container_weak.upgrade() { + requests_container.lock().handlers.remove(&self.id); + } } } @@ -147,9 +167,35 @@ struct RequestsContainer { handlers: HashedMap>>, } +#[derive(Default)] +struct FBSRequestsContainer { + next_id: u32, + handlers: HashedMap>, +} + +/* TODO: Remove. +impl Drop for RequestsContainer { + fn drop(&mut self) { + panic!(); + } +} +*/ +/* +struct OutgoingMessageRequest { + message: Vec, + payload: Vec, +} + +enum OutgoingMessage { + Request(Arc>), + Notification { message: Vec, payload: Vec }, +} +*/ + struct OutgoingMessageBuffer { handle: Option, messages: VecDeque>>>, + // messages: VecDeque, } #[allow(clippy::type_complexity)] @@ -157,8 +203,13 @@ struct Inner { outgoing_message_buffer: Arc>, internal_message_receiver: async_channel::Receiver, requests_container_weak: Weak>, + fbs_requests_container_weak: Weak>, buffered_notifications_for: Arc>>>>, + fbs_buffered_notifications_for: Arc>>>>, event_handlers_weak: WeakEventHandlers>, + fbs_event_handlers_weak: FBSWeakEventHandlers< + Arc) + Send + Sync + 'static>, + >, worker_closed: Arc, closed: AtomicBool, } @@ -184,10 +235,16 @@ impl Channel { })); let requests_container = Arc::>::default(); let requests_container_weak = Arc::downgrade(&requests_container); + let fbs_requests_container = Arc::>::default(); + let fbs_requests_container_weak = Arc::downgrade(&fbs_requests_container); let buffered_notifications_for = Arc::>>>>::default(); + let fbs_buffered_notifications_for = + Arc::>>>>::default(); let event_handlers = EventHandlers::new(); + let fbs_event_handlers = FBSEventHandlers::new(); let event_handlers_weak = event_handlers.downgrade(); + let fbs_event_handlers_weak = fbs_event_handlers.downgrade(); let prepared_channel_read = utils::prepare_channel_read_fn({ let outgoing_message_buffer = Arc::clone(&outgoing_message_buffer); @@ -213,6 +270,7 @@ impl Channel { let prepared_channel_write = utils::prepare_channel_write_fn({ let buffered_notifications_for = Arc::clone(&buffered_notifications_for); + let fbs_buffered_notifications_for = Arc::clone(&fbs_buffered_notifications_for); // This this contain cache of targets that are known to not have buffering, so // that we can avoid Mutex locking overhead for them let mut non_buffered_notifications = LruCache::::new( @@ -223,7 +281,11 @@ impl Channel { trace!("received raw message: {}", String::from_utf8_lossy(message)); match deserialize_message(message) { - ChannelReceiveMessage::Notification { target_id } => { + ChannelReceiveMessage::Notification(notification) => { + let target_id: SubscriptionTarget = SubscriptionTarget::String( + notification.handler_id().unwrap().unwrap().to_string(), + ); + if !non_buffered_notifications.contains(&target_id) { let mut buffer_notifications_for = buffered_notifications_for.lock(); // Check if we need to buffer notifications for this @@ -232,31 +294,54 @@ impl Channel { list.push(Vec::from(message)); return; } + let mut fbs_buffer_notifications_for = + fbs_buffered_notifications_for.lock(); + // Check if we need to buffer notifications for this + // target_id + if let Some(list) = fbs_buffer_notifications_for.get_mut(&target_id) { + list.push(Vec::from(message)); + return; + } // Remember we don't need to buffer these - non_buffered_notifications.put(target_id, ()); + non_buffered_notifications.put(target_id.clone(), ()); } - event_handlers.call_callbacks_with_single_value(&target_id, message); + fbs_event_handlers + .call_callbacks_with_single_value(&target_id, notification); } - ChannelReceiveMessage::ResponseSuccess { id, data, .. } => { - let sender = requests_container.lock().handlers.remove(&id); + ChannelReceiveMessage::Response(response) => { + let sender = fbs_requests_container + .lock() + .handlers + .remove(&response.id().unwrap()); if let Some(mut sender) = sender { - let _ = sender.send(Ok(data)); + // Request did not succeed. + if let Ok(Some(error)) = response.error() { + let _ = sender.send(Err(ResponseError { + reason: error.to_string(), + })); + } + // Request succeeded. + else { + match response.body().expect("failed accessing response body") { + // Response has body. + Some(body_ref) => { + let _ = sender.send(Ok(Some( + body_ref + .try_into() + .expect("failed to retrieve response body"), + ))); + } + // Response does not have body. + None => { + let _ = sender.send(Ok(None)); + } + } + } } else { warn!( "received success response does not match any sent request [id:{}]", - id, - ); - } - } - ChannelReceiveMessage::ResponseError { id, reason } => { - let sender = requests_container.lock().handlers.remove(&id); - if let Some(mut sender) = sender { - let _ = sender.send(Err(ResponseError { reason })); - } else { - warn!( - "received error response does not match any sent request [id:{}]", - id, + response.id().unwrap(), ); } } @@ -271,8 +356,11 @@ impl Channel { outgoing_message_buffer, internal_message_receiver, requests_container_weak, + fbs_requests_container_weak, buffered_notifications_for, + fbs_buffered_notifications_for, event_handlers_weak, + fbs_event_handlers_weak, worker_closed, closed: AtomicBool::new(false), }); @@ -292,15 +380,23 @@ impl Channel { /// being created. This allows to avoid missing notifications due to race conditions. pub(crate) fn buffer_messages_for(&self, target_id: SubscriptionTarget) -> BufferMessagesGuard { let buffered_notifications_for = Arc::clone(&self.inner.buffered_notifications_for); + let fbs_buffered_notifications_for = Arc::clone(&self.inner.fbs_buffered_notifications_for); let event_handlers_weak = self.inner.event_handlers_weak.clone(); + let fbs_event_handlers_weak = self.inner.fbs_event_handlers_weak.clone(); buffered_notifications_for .lock() - .entry(target_id) + .entry(target_id.clone()) + .or_default(); + fbs_buffered_notifications_for + .lock() + .entry(target_id.clone()) .or_default(); BufferMessagesGuard { target_id, buffered_notifications_for, + fbs_buffered_notifications_for, event_handlers_weak, + fbs_event_handlers_weak, } } @@ -433,6 +529,155 @@ impl Channel { } } + pub(crate) async fn request_fbs( + &self, + mut builder: Builder, + handler_id: HandlerId, + method: request::Method, + body: Option>, + ) -> Result, RequestError> + where + HandlerId: Display, + { + let id; + let (result_sender, result_receiver) = async_oneshot::oneshot(); + + { + let requests_container = match self.inner.fbs_requests_container_weak.upgrade() { + Some(requests_container_lock) => requests_container_lock, + None => { + return Err(RequestError::ChannelClosed); + } + }; + let mut requests_container_lock = requests_container.lock(); + + id = requests_container_lock.next_id; + + requests_container_lock.next_id = requests_container_lock.next_id.wrapping_add(1); + requests_container_lock.handlers.insert(id, result_sender); + } + + debug!("request() [method:{:?}, id:{}]", method, id); + + let request = + request::Request::create(&mut builder, id, method, handler_id.to_string(), body); + + let message_body = message::Body::create_request(&mut builder, request); + let message = message::Message::create(&mut builder, message::Type::Request, message_body); + + let data = builder.finish(message, None).to_vec(); + + let buffer = Arc::new(AtomicTake::new(data)); + + { + let mut outgoing_message_buffer = self.inner.outgoing_message_buffer.lock(); + outgoing_message_buffer + .messages + .push_back(Arc::clone(&buffer)); + if let Some(handle) = outgoing_message_buffer.handle { + if self.inner.worker_closed.load(Ordering::Acquire) { + // Forbid all requests after worker closing except one worker closing request + if method != request::Method::WorkerClose { + return Err(RequestError::ChannelClosed); + } + } + unsafe { + // Notify worker that there is something to read + let ret = mediasoup_sys::uv_async_send(handle); + if ret != 0 { + error!("uv_async_send call failed with code {}", ret); + + return Err(RequestError::ChannelClosed); + } + } + } + } + + // Drop guard to make sure to drop pending request when future is cancelled + let request_drop_guard = RequestDropGuard { + id, + message: buffer, + channel: self, + removed: false, + }; + + let response_result_fut = result_receiver.await; + + request_drop_guard.remove(); + + let response_result = match response_result_fut { + Ok(response_result) => response_result, + Err(_closed) => Err(ResponseError { + reason: String::from("ChannelClosed"), + }), + }; + + match response_result { + Ok(data) => { + debug!("request succeeded [method:{:?}, id:{}]", method, id); + + Ok(data) + } + Err(ResponseError { reason }) => { + debug!( + "request failed [method:{:?}, id:{}]: {}", + method, id, reason + ); + if reason.contains("not found") { + Err(RequestError::ChannelClosed) + } else { + Err(RequestError::Response { reason }) + } + } + } + } + + pub(crate) fn notify( + &self, + handler_id: HandlerId, + notification: N, + // payload: Vec, + ) -> Result<(), NotificationError> + where + N: Notification, + HandlerId: Display, + { + debug!("notify() [event:{}]", notification.as_event()); + + // TODO: Todo pre-allocate fixed size string sufficient for most cases by default + // TODO: Refactor to avoid extra allocation during JSON serialization if possible + let message = Arc::new(AtomicTake::new( + format!( + "n:{}:{handler_id}:{}", + notification.as_event(), + serde_json::to_string(¬ification).unwrap() + ) + .into_bytes(), + )); + + { + let mut outgoing_message_buffer = self.inner.outgoing_message_buffer.lock(); + outgoing_message_buffer + .messages + .push_back(Arc::clone(&message)); + // .push_back(OutgoingMessage::Notification { message, payload }); + if let Some(handle) = outgoing_message_buffer.handle { + if self.inner.worker_closed.load(Ordering::Acquire) { + return Err(NotificationError::ChannelClosed); + } + unsafe { + // Notify worker that there is something to read + let ret = mediasoup_sys::uv_async_send(handle); + if ret != 0 { + error!("uv_async_send call failed with code {}", ret); + return Err(NotificationError::ChannelClosed); + } + } + } + } + + Ok(()) + } pub(crate) fn subscribe_to_notifications( &self, target_id: SubscriptionTarget, @@ -446,4 +691,17 @@ impl Channel { .upgrade() .map(|event_handlers| event_handlers.add(target_id, Arc::new(callback))) } + pub(crate) fn subscribe_to_fbs_notifications( + &self, + target_id: SubscriptionTarget, + callback: F, + ) -> Option + where + F: Fn(notification::NotificationRef<'_>) + Send + Sync + 'static, + { + self.inner + .fbs_event_handlers_weak + .upgrade() + .map(|fbs_event_handlers| fbs_event_handlers.add(target_id, Arc::new(callback))) + } } diff --git a/rust/src/worker/common.rs b/rust/src/worker/common.rs index 6616b48c17..4af1b551e3 100644 --- a/rust/src/worker/common.rs +++ b/rust/src/worker/common.rs @@ -1,3 +1,4 @@ +use crate::fbs::notification; use hash_hasher::HashedMap; use nohash_hasher::IntMap; use parking_lot::Mutex; @@ -24,6 +25,11 @@ pub(super) struct EventHandlers { handlers: Arc>>>, } +#[derive(Clone)] +pub(super) struct FBSEventHandlers { + handlers: Arc>>>, +} + impl EventHandlers { pub(super) fn new() -> Self { let handlers = Arc::>>>::default(); @@ -35,7 +41,7 @@ impl EventHandlers { { let mut event_handlers = self.handlers.lock(); let list = event_handlers - .entry(target_id) + .entry(target_id.clone()) .or_insert_with(EventHandlersList::default); index = list.index; list.index += 1; @@ -79,6 +85,61 @@ impl EventHandlers { } } +impl FBSEventHandlers { + pub(super) fn new() -> Self { + let handlers = Arc::>>>::default(); + Self { handlers } + } + + pub(super) fn add(&self, target_id: SubscriptionTarget, callback: F) -> SubscriptionHandler { + let index; + { + let mut event_handlers = self.handlers.lock(); + let list = event_handlers + .entry(target_id.clone()) + .or_insert_with(EventHandlersList::default); + index = list.index; + list.index += 1; + list.callbacks.insert(index, callback); + drop(event_handlers); + } + + SubscriptionHandler::new({ + let event_handlers_weak = Arc::downgrade(&self.handlers); + + Box::new(move || { + if let Some(event_handlers) = event_handlers_weak.upgrade() { + // We store removed handler here in order to drop after `event_handlers` lock is + // released, otherwise handler will be dropped on removal from callbacks + // immediately and if it happens to hold another entity that held subscription + // handler, we may arrive here again trying to acquire lock that we didn't + // release yet. By dropping callback only when lock is released we avoid + // deadlocking. + let removed_handler; + { + let mut handlers = event_handlers.lock(); + let is_empty = { + let list = handlers.get_mut(&target_id).unwrap(); + removed_handler = list.callbacks.remove(&index); + list.callbacks.is_empty() + }; + if is_empty { + handlers.remove(&target_id); + } + } + drop(removed_handler); + } + }) + }) + } + + pub(super) fn downgrade(&self) -> FBSWeakEventHandlers { + FBSWeakEventHandlers { + handlers: Arc::downgrade(&self.handlers), + } + } +} + impl EventHandlers> { pub(super) fn call_callbacks_with_single_value( &self, @@ -94,17 +155,16 @@ impl EventHandlers> { } } -impl EventHandlers> { - pub(super) fn call_callbacks_with_two_values( +impl FBSEventHandlers) + Send + Sync + 'static>> { + pub(super) fn call_callbacks_with_single_value( &self, target_id: &SubscriptionTarget, - value1: &V1, - value2: &V2, + value: notification::NotificationRef<'_>, ) { let handlers = self.handlers.lock(); if let Some(list) = handlers.get(target_id) { for callback in list.callbacks.values() { - callback(value1, value2); + callback(value); } } } @@ -123,23 +183,24 @@ impl WeakEventHandlers { } } -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Deserialize)] -#[serde(untagged)] -pub(crate) enum SubscriptionTarget { - Uuid(Uuid), - Number(u64), +#[derive(Clone)] +pub(super) struct FBSWeakEventHandlers { + handlers: Weak>>>, } -impl From for SubscriptionTarget { - fn from(number: u32) -> Self { - Self::Number(u64::from(number)) +impl FBSWeakEventHandlers { + pub(super) fn upgrade(&self) -> Option> { + self.handlers + .upgrade() + .map(|handlers| FBSEventHandlers { handlers }) } } -impl From for SubscriptionTarget { - fn from(number: u64) -> Self { - Self::Number(number) - } +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)] +#[serde(untagged)] +pub(crate) enum SubscriptionTarget { + Uuid(Uuid), + String(String), } /// Subscription handler, will remove corresponding subscription when dropped diff --git a/rust/src/worker/payload_channel.rs b/rust/src/worker/payload_channel.rs deleted file mode 100644 index c4a7ed3172..0000000000 --- a/rust/src/worker/payload_channel.rs +++ /dev/null @@ -1,398 +0,0 @@ -use crate::messages::{Notification, Request}; -use crate::worker::common::{EventHandlers, SubscriptionTarget, WeakEventHandlers}; -use crate::worker::utils::{PreparedPayloadChannelRead, PreparedPayloadChannelWrite}; -use crate::worker::{utils, RequestError, SubscriptionHandler}; -use atomic_take::AtomicTake; -use log::{debug, error, trace, warn}; -use mediasoup_sys::UvAsyncT; -use nohash_hasher::IntMap; -use parking_lot::Mutex; -use serde::Deserialize; -use serde_json::Value; -use std::collections::VecDeque; -use std::fmt::{Debug, Display}; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::{Arc, Weak}; -use thiserror::Error; - -#[derive(Debug)] -pub(super) enum InternalMessage { - /// Unknown data - UnexpectedData(Vec), -} - -#[derive(Debug, Deserialize)] -#[serde(untagged)] -enum PayloadChannelReceiveMessage { - #[serde(rename_all = "camelCase")] - Notification { target_id: SubscriptionTarget }, - ResponseSuccess { - id: u32, - // The following field is present, unused, but needed for differentiating successful - // response from error case - #[allow(dead_code)] - accepted: bool, - data: Option, - }, - ResponseError { - id: u32, - // The following field is present, but unused - // error: Value, - reason: String, - }, - /// Unknown data - #[serde(skip)] - Internal(InternalMessage), -} - -fn deserialize_message(bytes: &[u8]) -> PayloadChannelReceiveMessage { - match serde_json::from_slice(bytes) { - Ok(message) => message, - Err(error) => { - warn!("Failed to deserialize message: {}", error); - - PayloadChannelReceiveMessage::Internal(InternalMessage::UnexpectedData(Vec::from( - bytes, - ))) - } - } -} - -struct ResponseError { - reason: String, -} - -type ResponseResult = Result, ResponseError>; - -struct RequestDropGuard<'a> { - id: u32, - message_with_payload: Arc>, - channel: &'a PayloadChannel, - removed: bool, -} - -impl<'a> Drop for RequestDropGuard<'a> { - fn drop(&mut self) { - if self.removed { - return; - } - - // Drop pending message from memory - self.message_with_payload.take(); - // Remove request handler from the container - if let Some(requests_container) = self.channel.inner.requests_container_weak.upgrade() { - requests_container.lock().handlers.remove(&self.id); - } - } -} - -impl<'a> RequestDropGuard<'a> { - fn remove(mut self) { - self.removed = true; - } -} - -#[derive(Default)] -struct RequestsContainer { - next_id: u32, - handlers: IntMap>>, -} - -struct OutgoingMessageRequest { - message: Vec, - payload: Vec, -} - -enum OutgoingMessage { - Request(Arc>), - Notification { message: Vec, payload: Vec }, -} - -struct OutgoingMessageBuffer { - handle: Option, - messages: VecDeque, -} - -#[derive(Debug, Error, Eq, PartialEq)] -pub enum NotificationError { - #[error("Channel already closed")] - ChannelClosed, -} - -struct Inner { - outgoing_message_buffer: Arc>, - internal_message_receiver: async_channel::Receiver, - requests_container_weak: Weak>, - #[allow(clippy::type_complexity)] - event_handlers_weak: WeakEventHandlers>, - worker_closed: Arc, -} - -impl Drop for Inner { - fn drop(&mut self) { - self.internal_message_receiver.close(); - } -} - -#[derive(Clone)] -pub(crate) struct PayloadChannel { - inner: Arc, -} - -impl PayloadChannel { - pub(super) fn new( - worker_closed: Arc, - ) -> ( - Self, - PreparedPayloadChannelRead, - PreparedPayloadChannelWrite, - ) { - let outgoing_message_buffer = Arc::new(Mutex::new(OutgoingMessageBuffer { - handle: None, - messages: VecDeque::with_capacity(10), - })); - let requests_container = Arc::>::default(); - let requests_container_weak = Arc::downgrade(&requests_container); - let event_handlers = EventHandlers::new(); - let event_handlers_weak = event_handlers.downgrade(); - - let prepared_payload_channel_read = utils::prepare_payload_channel_read_fn({ - let outgoing_message_buffer = Arc::clone(&outgoing_message_buffer); - - move |handle| { - let mut outgoing_message_buffer = outgoing_message_buffer.lock(); - if outgoing_message_buffer.handle.is_none() { - outgoing_message_buffer.handle.replace(handle); - } - - while let Some(outgoing_message) = outgoing_message_buffer.messages.pop_front() { - match outgoing_message { - OutgoingMessage::Request(maybe_message) => { - // Request might have already been cancelled - if let Some(OutgoingMessageRequest { message, payload }) = - maybe_message.take() - { - return Some((message, payload)); - } - } - OutgoingMessage::Notification { message, payload } => { - return Some((message, payload)); - } - } - } - - None - } - }); - - let (internal_message_sender, internal_message_receiver) = async_channel::bounded(1); - - let prepared_payload_channel_write = - utils::prepare_payload_channel_write_fn(move |message, payload| { - trace!("received raw message: {}", String::from_utf8_lossy(message)); - - match deserialize_message(message) { - PayloadChannelReceiveMessage::Notification { target_id } => { - trace!("received notification payload of {} bytes", payload.len()); - - event_handlers.call_callbacks_with_two_values(&target_id, message, payload); - } - PayloadChannelReceiveMessage::ResponseSuccess { id, data, .. } => { - let sender = requests_container.lock().handlers.remove(&id); - if let Some(mut sender) = sender { - let _ = sender.send(Ok(data)); - } else { - warn!( - "received success response does not match any sent request [id:{}]", - id, - ); - } - } - PayloadChannelReceiveMessage::ResponseError { id, reason } => { - let sender = requests_container.lock().handlers.remove(&id); - if let Some(mut sender) = sender { - let _ = sender.send(Err(ResponseError { reason })); - } else { - warn!( - "received error response does not match any sent request [id:{}]", - id, - ); - } - } - PayloadChannelReceiveMessage::Internal(internal_message) => { - let _ = internal_message_sender.try_send(internal_message); - } - } - }); - - let inner = Arc::new(Inner { - outgoing_message_buffer, - internal_message_receiver, - requests_container_weak, - event_handlers_weak, - worker_closed, - }); - - ( - Self { inner }, - prepared_payload_channel_read, - prepared_payload_channel_write, - ) - } - - pub(super) fn get_internal_message_receiver(&self) -> async_channel::Receiver { - self.inner.internal_message_receiver.clone() - } - - pub(crate) async fn request( - &self, - handler_id: HandlerId, - request: R, - payload: Vec, - ) -> Result - where - R: Request, - HandlerId: Display, - { - let method = request.as_method(); - - let id; - let (result_sender, result_receiver) = async_oneshot::oneshot(); - - { - let requests_container_lock = self - .inner - .requests_container_weak - .upgrade() - .ok_or(RequestError::ChannelClosed)?; - let mut requests_container = requests_container_lock.lock(); - - id = requests_container.next_id; - - requests_container.next_id = requests_container.next_id.wrapping_add(1); - requests_container.handlers.insert(id, result_sender); - } - - debug!("request() [method:{}, id:{}]: {:?}", method, id, request); - - // TODO: Todo pre-allocate fixed size string sufficient for most cases by default - // TODO: Refactor to avoid extra allocation during JSON serialization if possible - let message = format!( - "r:{id}:{}:{handler_id}:{}", - request.as_method(), - serde_json::to_string(&request).unwrap() - ) - .into_bytes(); - - let message_with_payload = - Arc::new(AtomicTake::new(OutgoingMessageRequest { message, payload })); - - { - let mut outgoing_message_buffer = self.inner.outgoing_message_buffer.lock(); - outgoing_message_buffer - .messages - .push_back(OutgoingMessage::Request(Arc::clone(&message_with_payload))); - if let Some(handle) = outgoing_message_buffer.handle { - if self.inner.worker_closed.load(Ordering::Acquire) { - return Err(RequestError::ChannelClosed); - } - unsafe { - // Notify worker that there is something to read - let ret = mediasoup_sys::uv_async_send(handle); - if ret != 0 { - error!("uv_async_send call failed with code {}", ret); - return Err(RequestError::ChannelClosed); - } - } - } - } - - // Drop guard to make sure to drop pending request when future is cancelled - let request_drop_guard = RequestDropGuard { - id, - message_with_payload, - channel: self, - removed: false, - }; - - let response_result_fut = result_receiver.await; - - request_drop_guard.remove(); - - match response_result_fut.map_err(|_| RequestError::ChannelClosed {})? { - Ok(data) => { - debug!("request succeeded [method:{}, id:{}]", method, id); - - // Default will work for `()` response - serde_json::from_value(data.unwrap_or_default()).map_err(|error| { - RequestError::FailedToParse { - error: error.to_string(), - } - }) - } - Err(ResponseError { reason }) => { - debug!("request failed [method:{}, id:{}]: {}", method, id, reason); - - Err(RequestError::Response { reason }) - } - } - } - - pub(crate) fn notify( - &self, - handler_id: HandlerId, - notification: N, - payload: Vec, - ) -> Result<(), NotificationError> - where - N: Notification, - HandlerId: Display, - { - debug!("notify() [event:{}]", notification.as_event()); - - // TODO: Todo pre-allocate fixed size string sufficient for most cases by default - // TODO: Refactor to avoid extra allocation during JSON serialization if possible - let message = format!( - "n:{}:{handler_id}:{}", - notification.as_event(), - serde_json::to_string(¬ification).unwrap() - ) - .into_bytes(); - - { - let mut outgoing_message_buffer = self.inner.outgoing_message_buffer.lock(); - outgoing_message_buffer - .messages - .push_back(OutgoingMessage::Notification { message, payload }); - if let Some(handle) = outgoing_message_buffer.handle { - if self.inner.worker_closed.load(Ordering::Acquire) { - return Err(NotificationError::ChannelClosed); - } - unsafe { - // Notify worker that there is something to read - let ret = mediasoup_sys::uv_async_send(handle); - if ret != 0 { - error!("uv_async_send call failed with code {}", ret); - return Err(NotificationError::ChannelClosed); - } - } - } - } - - Ok(()) - } - - pub(crate) fn subscribe_to_notifications( - &self, - target_id: SubscriptionTarget, - callback: F, - ) -> Option - where - F: Fn(&[u8], &[u8]) + Send + Sync + 'static, - { - self.inner - .event_handlers_weak - .upgrade() - .map(|event_handlers| event_handlers.add(target_id, Arc::new(callback))) - } -} diff --git a/rust/src/worker/utils.rs b/rust/src/worker/utils.rs index 0c9735737c..3fa01ace77 100644 --- a/rust/src/worker/utils.rs +++ b/rust/src/worker/utils.rs @@ -2,15 +2,9 @@ mod channel_read_fn; mod channel_write_fn; use crate::worker::channel::BufferMessagesGuard; -use crate::worker::{Channel, PayloadChannel, WorkerId}; -pub(super) use channel_read_fn::{ - prepare_channel_read_fn, prepare_payload_channel_read_fn, PreparedChannelRead, - PreparedPayloadChannelRead, -}; -pub(super) use channel_write_fn::{ - prepare_channel_write_fn, prepare_payload_channel_write_fn, PreparedChannelWrite, - PreparedPayloadChannelWrite, -}; +use crate::worker::{Channel, WorkerId}; +pub(super) use channel_read_fn::{prepare_channel_read_fn, PreparedChannelRead}; +pub(super) use channel_write_fn::{prepare_channel_write_fn, PreparedChannelWrite}; use std::ffi::CString; use std::os::raw::{c_char, c_int}; use std::sync::atomic::AtomicBool; @@ -39,7 +33,6 @@ pub enum ExitError { pub(super) struct WorkerRunResult { pub(super) channel: Channel, - pub(super) payload_channel: PayloadChannel, pub(super) buffer_worker_messages_guard: BufferMessagesGuard, } @@ -55,9 +48,9 @@ where { let (channel, prepared_channel_read, prepared_channel_write) = Channel::new(Arc::clone(&worker_closed)); - let (payload_channel, prepared_payload_channel_read, prepared_payload_channel_write) = - PayloadChannel::new(worker_closed); - let buffer_worker_messages_guard = channel.buffer_messages_for(std::process::id().into()); + let buffer_worker_messages_guard = channel.buffer_messages_for( + super::common::SubscriptionTarget::String(std::process::id().to_string()), + ); std::thread::Builder::new() .name(format!("mediasoup-worker-{id}")) @@ -81,16 +74,6 @@ where prepared_channel_read.deconstruct(); let (channel_write_fn, channel_write_ctx, _channel_read_callback) = prepared_channel_write.deconstruct(); - let ( - payload_channel_read_fn, - payload_channel_read_ctx, - _payload_channel_write_callback, - ) = prepared_payload_channel_read.deconstruct(); - let ( - payload_channel_write_fn, - payload_channel_write_ctx, - _payload_channel_read_callback, - ) = prepared_payload_channel_write.deconstruct(); mediasoup_sys::mediasoup_worker_run( argc, @@ -104,10 +87,6 @@ where channel_read_ctx, channel_write_fn, channel_write_ctx, - payload_channel_read_fn, - payload_channel_read_ctx, - payload_channel_write_fn, - payload_channel_write_ctx, ) }; @@ -122,7 +101,6 @@ where WorkerRunResult { channel, - payload_channel, buffer_worker_messages_guard, } } diff --git a/rust/src/worker/utils/channel_read_fn.rs b/rust/src/worker/utils/channel_read_fn.rs index 902f87ef66..57cf3b0bf8 100644 --- a/rust/src/worker/utils/channel_read_fn.rs +++ b/rust/src/worker/utils/channel_read_fn.rs @@ -1,7 +1,5 @@ -pub(super) use mediasoup_sys::{ - ChannelReadCtx, ChannelReadFn, PayloadChannelReadCtx, PayloadChannelReadFn, -}; -use mediasoup_sys::{ChannelReadFreeFn, PayloadChannelReadFreeFn, UvAsyncT}; +pub(super) use mediasoup_sys::{ChannelReadCtx, ChannelReadFn}; +use mediasoup_sys::{ChannelReadFreeFn, UvAsyncT}; use std::mem; use std::os::raw::c_void; @@ -76,90 +74,3 @@ where write_callback: ChannelReadCallback(read_callback), } } - -#[allow(clippy::type_complexity)] -pub(super) struct PayloadChannelReadCallback( - Box Option<(Vec, Vec)>) + Send + 'static>, -); - -pub(crate) struct PreparedPayloadChannelRead { - payload_channel_read_fn: PayloadChannelReadFn, - payload_channel_read_ctx: PayloadChannelReadCtx, - write_callback: PayloadChannelReadCallback, -} - -impl PreparedPayloadChannelRead { - /// SAFETY: - /// 1) `PayloadChannelReadCallback` returned must be dropped AFTER last usage of returned - /// function and context pointers - /// 2) `PayloadChannelReadCtx` should not be called from multiple threads concurrently - pub(super) unsafe fn deconstruct( - self, - ) -> ( - PayloadChannelReadFn, - PayloadChannelReadCtx, - PayloadChannelReadCallback, - ) { - let Self { - payload_channel_read_fn, - payload_channel_read_ctx, - write_callback, - } = self; - ( - payload_channel_read_fn, - payload_channel_read_ctx, - write_callback, - ) - } -} - -/// Given callback function, prepares a pair of channel read function and context, which can be -/// provided to of C++ worker and worker will effectively call the callback whenever it wants to -/// read something from Rust (so it is reading from C++ point of view and writing from Rust). -pub(crate) fn prepare_payload_channel_read_fn(read_callback: F) -> PreparedPayloadChannelRead -where - F: (FnMut(UvAsyncT) -> Option<(Vec, Vec)>) + Send + 'static, -{ - unsafe extern "C" fn wrapper( - message: *mut *mut u8, - message_len: *mut u32, - message_capacity: *mut usize, - payload: *mut *mut u8, - payload_len: *mut u32, - payload_capacity: *mut usize, - handle: UvAsyncT, - PayloadChannelReadCtx(ctx): PayloadChannelReadCtx, - ) -> PayloadChannelReadFreeFn - where - F: (FnMut(UvAsyncT) -> Option<(Vec, Vec)>) + Send + 'static, - { - // Call Rust and try to get a new message (if there is any) - let (mut new_message, mut new_payload) = (*(ctx as *mut F))(handle)?; - - // Set pointers, give out control over memory to C++ - *message = new_message.as_mut_ptr(); - *message_len = new_message.len() as u32; - *message_capacity = new_message.capacity(); - *payload = new_payload.as_mut_ptr(); - *payload_len = new_payload.len() as u32; - *payload_capacity = new_payload.capacity(); - - // Forget about vectors in Rust - mem::forget(new_message); - mem::forget(new_payload); - - // Function pointer that C++ can use to free vectors later - Some(free_vec) - } - - // Move to heap to make sure it doesn't change address later on - let read_callback = Box::new(read_callback); - - PreparedPayloadChannelRead { - payload_channel_read_fn: wrapper::, - payload_channel_read_ctx: PayloadChannelReadCtx( - read_callback.as_ref() as *const F as *const c_void - ), - write_callback: PayloadChannelReadCallback(read_callback), - } -} diff --git a/rust/src/worker/utils/channel_write_fn.rs b/rust/src/worker/utils/channel_write_fn.rs index 968dafb79c..c9e72077c9 100644 --- a/rust/src/worker/utils/channel_write_fn.rs +++ b/rust/src/worker/utils/channel_write_fn.rs @@ -1,6 +1,4 @@ -pub(super) use mediasoup_sys::{ - ChannelWriteCtx, ChannelWriteFn, PayloadChannelWriteCtx, PayloadChannelWriteFn, -}; +pub(super) use mediasoup_sys::{ChannelWriteCtx, ChannelWriteFn}; use std::os::raw::c_void; use std::slice; @@ -59,72 +57,3 @@ where read_callback: ChannelReadCallback(read_callback), } } - -#[allow(clippy::type_complexity)] -pub(super) struct PayloadChannelReadCallback(Box); - -pub(crate) struct PreparedPayloadChannelWrite { - channel_write_fn: PayloadChannelWriteFn, - channel_write_ctx: PayloadChannelWriteCtx, - read_callback: PayloadChannelReadCallback, -} - -unsafe impl Send for PreparedPayloadChannelWrite {} - -impl PreparedPayloadChannelWrite { - /// SAFETY: - /// 1) `PayloadChannelReadCallback` returned must be dropped AFTER last usage of returned - /// function and context pointers - /// 2) `PayloadChannelWriteCtx` should not be called from multiple threads concurrently - pub(super) unsafe fn deconstruct( - self, - ) -> ( - PayloadChannelWriteFn, - PayloadChannelWriteCtx, - PayloadChannelReadCallback, - ) { - let Self { - channel_write_fn, - channel_write_ctx, - read_callback, - } = self; - (channel_write_fn, channel_write_ctx, read_callback) - } -} - -/// Given callback function, prepares a pair of channel write function and context, which can be -/// provided to of C++ worker and worker will effectively call the callback whenever it needs to -/// send something to Rust (so it is writing from C++ point of view and reading from Rust). -pub(crate) fn prepare_payload_channel_write_fn(read_callback: F) -> PreparedPayloadChannelWrite -where - F: FnMut(&[u8], &[u8]) + Send + 'static, -{ - unsafe extern "C" fn wrapper( - message: *const u8, - message_len: u32, - payload: *const u8, - payload_len: u32, - PayloadChannelWriteCtx(ctx): PayloadChannelWriteCtx, - ) where - F: FnMut(&[u8], &[u8]) + Send + 'static, - { - let message = slice::from_raw_parts(message, message_len as usize); - let payload = if payload_len == 0 { - &[] - } else { - slice::from_raw_parts(payload, payload_len as usize) - }; - (*(ctx as *mut F))(message, payload); - } - - // Move to heap to make sure it doesn't change address later on - let read_callback = Box::new(read_callback); - - PreparedPayloadChannelWrite { - channel_write_fn: wrapper::, - channel_write_ctx: PayloadChannelWriteCtx( - read_callback.as_ref() as *const F as *const c_void - ), - read_callback: PayloadChannelReadCallback(read_callback), - } -} diff --git a/rust/tests/integration/router.rs b/rust/tests/integration/router.rs index 66889e2f5b..56d056d5a9 100644 --- a/rust/tests/integration/router.rs +++ b/rust/tests/integration/router.rs @@ -111,8 +111,7 @@ fn create_router_succeeds() { worker_dump.channel_message_handlers, ChannelMessageHandlers { channel_request_handlers: vec![router.id().into()], - payload_channel_request_handlers: vec![], - payload_channel_notification_handlers: vec![] + channel_notification_handlers: vec![] } ); diff --git a/rust/tests/integration/webrtc_server.rs b/rust/tests/integration/webrtc_server.rs index b4600cd09f..a4f572ffa0 100644 --- a/rust/tests/integration/webrtc_server.rs +++ b/rust/tests/integration/webrtc_server.rs @@ -101,8 +101,7 @@ fn create_webrtc_server_succeeds() { worker_dump.channel_message_handlers, ChannelMessageHandlers { channel_request_handlers: vec![webrtc_server.id().into()], - payload_channel_request_handlers: vec![], - payload_channel_notification_handlers: vec![] + channel_notification_handlers: vec![] } ); diff --git a/rust/tests/integration/worker.rs b/rust/tests/integration/worker.rs index 1ae513b746..ad0a3d7d9a 100644 --- a/rust/tests/integration/worker.rs +++ b/rust/tests/integration/worker.rs @@ -150,8 +150,7 @@ fn dump_succeeds() { dump.channel_message_handlers, ChannelMessageHandlers { channel_request_handlers: vec![], - payload_channel_request_handlers: vec![], - payload_channel_notification_handlers: vec![] + channel_notification_handlers: vec![] } ); }); diff --git a/worker/.clang-format b/worker/.clang-format index 00181a08c8..8e9955b0d2 100644 --- a/worker/.clang-format +++ b/worker/.clang-format @@ -49,7 +49,7 @@ FixNamespaceComments: true IncludeCategories: - Regex: '"common.hpp"' Priority: 1 - - Regex: '^"(Channel|PayloadChannel|RTC|Utils|handles)/' + - Regex: '^"(Channel|PayloadChannel|FBS|RTC|Utils|handles)/' Priority: 3 - Regex: '"*"' Priority: 2 diff --git a/worker/Makefile b/worker/Makefile index 3e8fc4eac7..4862f4266f 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -21,6 +21,8 @@ INSTALL_DIR ?= $(MEDIASOUP_OUT_DIR)/$(MEDIASOUP_BUILDTYPE) BUILD_DIR ?= $(INSTALL_DIR)/build MESON ?= $(PIP_DIR)/bin/meson MESON_VERSION ?= 0.61.5 +FLATC ?= $(BUILD_DIR)/subprojects/flatbuffers-23.3.3/flatc +FLATC_OUT_DIR ?= ./include/FBS # `MESON_ARGS` can be used to provide extra configuration parameters to Meson, # such as adding defines or changing optimization options. For instance, use # `MESON_ARGS="-Dms_log_trace=true -Dms_log_file_line=true" npm i` to compile @@ -77,6 +79,7 @@ endif update-wrap-file \ mediasoup-worker \ libmediasoup-worker \ + flatc \ xcode \ lint \ format \ @@ -194,16 +197,29 @@ clean-all: clean-subprojects update-wrap-file: meson-ninja $(MESON) subprojects update --reset $(SUBPROJECT) -mediasoup-worker: setup +mediasoup-worker: setup flatc ifeq ($(MEDIASOUP_WORKER_BIN),) $(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker $(MESON) install -C $(BUILD_DIR) --no-rebuild --tags mediasoup-worker endif -libmediasoup-worker: setup +libmediasoup-worker: setup flatc $(MESON) compile -C $(BUILD_DIR) -j $(CORES) libmediasoup-worker $(MESON) install -C $(BUILD_DIR) --no-rebuild --tags libmediasoup-worker +flatc: + $(MESON) compile -C $(BUILD_DIR) flatc + [ -d $(FLATC_OUT_DIR) ] || \ + $(FLATC) --cpp --cpp-field-case-style lower --reflect-names --scoped-enums \ + -o $(FLATC_OUT_DIR) ./fbs/* + +flatc-clean: + $(RM) -rf $(FLATC_OUT_DIR) + +flatc-force: flatc-clean flatc + +flatc-all: setup flatc + xcode: setup $(MESON) setup --buildtype debug --backend xcode $(MEDIASOUP_OUT_DIR)/xcode diff --git a/worker/deps/libwebrtc/meson.build b/worker/deps/libwebrtc/meson.build index 7d2c54e219..5e91710aa5 100644 --- a/worker/deps/libwebrtc/meson.build +++ b/worker/deps/libwebrtc/meson.build @@ -51,7 +51,6 @@ abseil_cpp_proj = subproject( 'warning_level=0', ], ) - local_include_directories = declare_dependency( include_directories: include_directories('libwebrtc') ) @@ -64,7 +63,7 @@ libwebrtc = library( openssl_proj.get_variable('openssl_dep'), abseil_cpp_proj.get_variable('absl_strings_dep'), abseil_cpp_proj.get_variable('absl_types_dep'), - nlohmann_json_proj.get_variable('nlohmann_json_dep'), + flatbuffers_proj.get_variable('flatbuffers_dep'), libuv_proj.get_variable('libuv_dep'), ], include_directories: libwebrtc_include_directories, diff --git a/worker/fbs/activeSpeakerObserver.fbs b/worker/fbs/activeSpeakerObserver.fbs new file mode 100644 index 0000000000..02c592eb41 --- /dev/null +++ b/worker/fbs/activeSpeakerObserver.fbs @@ -0,0 +1,11 @@ +namespace FBS.ActiveSpeakerObserver; + +table ActiveSpeakerObserverOptions { + interval:uint16; +} + +// Notifications from Worker. + +table DominantSpeakerNotification { + producer_id:string (required); +} diff --git a/worker/fbs/audioLevelObserver.fbs b/worker/fbs/audioLevelObserver.fbs new file mode 100644 index 0000000000..391e7225a3 --- /dev/null +++ b/worker/fbs/audioLevelObserver.fbs @@ -0,0 +1,18 @@ +namespace FBS.AudioLevelObserver; + +table AudioLevelObserverOptions { + max_entries:uint16; + threshold:int8; + interval:uint16; +} + +// Notifications from Worker. + +table Volume { + producer_id:string (required); + volume:int8; +} + +table VolumesNotification { + volumes:[Volume] (required); +} diff --git a/worker/fbs/common.fbs b/worker/fbs/common.fbs new file mode 100644 index 0000000000..f068118f45 --- /dev/null +++ b/worker/fbs/common.fbs @@ -0,0 +1,28 @@ + +namespace FBS.Common; + +table StringString { + key:string (required); + value:string (required); +} + +table StringUint8 { + key:string (required); + value:uint8; +} + +table Uint16String { + key:uint16; + value:string (required); +} + +table Uint32String { + key:uint32; + value:string (required); +} + +table StringStringArray { + key:string (required); + values:[string]; +} + diff --git a/worker/fbs/consumer.fbs b/worker/fbs/consumer.fbs new file mode 100644 index 0000000000..673269e848 --- /dev/null +++ b/worker/fbs/consumer.fbs @@ -0,0 +1,144 @@ +include "rtpParameters.fbs"; +include "rtpStream.fbs"; + +namespace FBS.Consumer; + +table ConsumerLayers { + spatial_layer:int16; + temporal_layer:int16 = null; +} + +table ConsumerScore { + score:uint8; + producer_score:uint8; + producer_scores:[uint8]; +} + +table SetPreferredLayersRequest { + preferred_layers:ConsumerLayers (required); +} + +table SetPreferredLayersResponse { + preferred_layers:ConsumerLayers; +} + +table SetPriorityRequest { + priority:uint8; +} + +table SetPriorityResponse { + priority:uint8; +} + +table EnableTraceEventRequest { + events:[string] (required); +} + +union DumpData { + SimpleConsumerDump, + SimulcastConsumerDump, + SvcConsumerDump, + PipeConsumerDump, +} + +table DumpResponse { + data: DumpData; + type:FBS.RtpParameters.Type; +} + +table BaseConsumerDump { + id:string (required); + producer_id:string (required); + kind:FBS.RtpParameters.MediaKind; + rtp_parameters:FBS.RtpParameters.RtpParameters (required); + consumable_rtp_encodings:[FBS.RtpParameters.RtpEncodingParameters]; + supported_codec_payload_types:[uint8]; + trace_event_types:[string] (required); + paused:bool = false; + producer_paused:bool = false; + priority:uint8; +} + +table SimpleConsumerDump { + base:BaseConsumerDump (required); + rtp_stream:FBS.RtpStream.Dump (required); +} + +table SimulcastConsumerDump { + base:BaseConsumerDump (required); + rtp_stream:FBS.RtpStream.Dump (required); + preferred_spatial_layer:int16; + target_spatial_layer:int16; + current_spatial_layer:int16; + preferred_temporal_layer:int16; + target_temporal_layer:int16; + current_temporal_layer:int16; +} + +table SvcConsumerDump { + base:BaseConsumerDump (required); + rtp_stream:FBS.RtpStream.Dump (required); + preferred_spatial_layer:int16; + target_spatial_layer:int16; + current_spatial_layer:int16; + preferred_temporal_layer:int16; + target_temporal_layer:int16; + current_temporal_layer:int16; +} + +table PipeConsumerDump { + base:BaseConsumerDump (required); + rtp_streams:[FBS.RtpStream.Dump] (required); +} + +table GetStatsResponse { + stats:[FBS.RtpStream.Stats]; +} + +// Notifications from Worker. + +table LayersChangeNotification { + layers:ConsumerLayers; +} + +table RtpNotification { + data:[ubyte] (required); +} + +table ScoreNotification { + score:ConsumerScore (required); +} + +enum TraceType: uint8 { KEYFRAME = 0, FIR, NACK, PLI, RTP, } +// NOTE (windows): IN|OUT are macros defined in windef.h. +enum TraceDirection: uint8 { DIRECTION_IN = 0, DIRECTION_OUT } + +union TraceInfo { + KeyFrameTraceInfo, + FirTraceInfo, + PliTraceInfo, + RtpTraceInfo, +} + +table KeyFrameTraceInfo { + is_rtx:bool; +} + +table FirTraceInfo { + ssrc:uint32; +} + +table PliTraceInfo { + ssrc:uint32; +} + +table RtpTraceInfo { + is_rtx:bool; +} + +table TraceNotification { + type: TraceType; + timestamp: uint64; + direction: TraceDirection; + info: TraceInfo; +} diff --git a/worker/fbs/dataConsumer.fbs b/worker/fbs/dataConsumer.fbs new file mode 100644 index 0000000000..bd8a376303 --- /dev/null +++ b/worker/fbs/dataConsumer.fbs @@ -0,0 +1,59 @@ +include "common.fbs"; +include "sctpParameters.fbs"; + +namespace FBS.DataConsumer; + +table GetBufferedAmountResponse { + buffered_amount:uint32; +} + +table SetBufferedAmountLowThresholdRequest { + threshold:uint32; +} + +table DumpResponse { + id:string (required); + data_producer_id:string (required); + type:string (required); + sctp_stream_parameters: FBS.SctpParameters.SctpStreamParameters; + label:string (required); + protocol:string (required); +} + +table GetStatsResponse { + timestamp:uint64; + label:string (required); + protocol:string (required); + messages_sent:uint64; + bytes_sent:uint64; + buffered_amount:uint32; +} + +table String { + value:string (required); +} + +table Binary { + value:[uint8] (required); +} + +union Data { + String, + Binary +} + +table SendRequest { + ppid:uint8; + data:Data (required); +} + +// Notifications from Worker. + +table BufferedAmountLowNotification { + buffered_amount:uint32; +} + +table MessageNotification { + ppid:uint32; + data:[ubyte] (required); +} diff --git a/worker/fbs/dataProducer.fbs b/worker/fbs/dataProducer.fbs new file mode 100644 index 0000000000..0d05717010 --- /dev/null +++ b/worker/fbs/dataProducer.fbs @@ -0,0 +1,38 @@ +include "sctpParameters.fbs"; + +namespace FBS.DataProducer; + +table DumpResponse { + id:string (required); + type:string (required); + sctp_stream_parameters: FBS.SctpParameters.SctpStreamParameters; + label:string (required); + protocol:string (required); +} + +table GetStatsResponse { + timestamp:uint64; + label:string (required); + protocol:string (required); + messages_received:uint64; + bytes_received:uint64; + buffered_amount:uint32; +} + +table String { + value:string (required); +} + +table Binary { + value:[uint8] (required); +} + +union Data { + String, + Binary +} + +table SendNotification { + ppid:uint8; + data:Data (required); +} diff --git a/worker/fbs/directTransport.fbs b/worker/fbs/directTransport.fbs new file mode 100644 index 0000000000..3ea467cebd --- /dev/null +++ b/worker/fbs/directTransport.fbs @@ -0,0 +1,21 @@ +include "transport.fbs"; + +namespace FBS.DirectTransport; + +table DirectTransportOptions { + base:FBS.Transport.Options (required); +} + +table DumpResponse { + base:FBS.Transport.Dump (required); +} + +table GetStatsResponse { + base:FBS.Transport.Stats (required); +} + +// Notifications from Worker. + +table RtcpNotification { + data:[ubyte] (required); +} diff --git a/worker/fbs/log.fbs b/worker/fbs/log.fbs new file mode 100644 index 0000000000..2558db8eee --- /dev/null +++ b/worker/fbs/log.fbs @@ -0,0 +1,6 @@ + +namespace FBS.Log; + +table Log { + data:string (required); +} diff --git a/worker/fbs/message.fbs b/worker/fbs/message.fbs new file mode 100644 index 0000000000..80fca0c762 --- /dev/null +++ b/worker/fbs/message.fbs @@ -0,0 +1,27 @@ +include "log.fbs"; +include "notification.fbs"; +include "request.fbs"; +include "response.fbs"; + +namespace FBS.Message; + +enum Type : uint8 { + REQUEST = 0, + RESPONSE, + NOTIFICATION, + LOG, +} + +union Body { + FBS.Request.Request, + FBS.Response.Response, + FBS.Notification.Notification, + FBS.Log.Log, +} + +table Message { + type:Type; + data:Body (required); +} + +root_type Message; diff --git a/worker/fbs/notification.fbs b/worker/fbs/notification.fbs new file mode 100644 index 0000000000..378fa3bc9c --- /dev/null +++ b/worker/fbs/notification.fbs @@ -0,0 +1,78 @@ +include "transport.fbs"; +include "webRtcTransport.fbs"; +include "plainTransport.fbs"; +include "directTransport.fbs"; +include "producer.fbs"; +include "dataProducer.fbs"; +include "dataConsumer.fbs"; +include "activeSpeakerObserver.fbs"; +include "audioLevelObserver.fbs"; + +namespace FBS.Notification; + +enum Event: uint8 { + // Notifications to worker. + TRANSPORT_SEND_RTCP = 0, + PRODUCER_SEND, + DATA_PRODUCER_SEND, + // Notifications from worker. + WORKER_RUNNING, + TRANSPORT_SCTP_STATE_CHANGE, + TRANSPORT_TRACE, + WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE, + WEBRTCTRANSPORT_ICE_STATE_CHANGE, + WEBRTCTRANSPORT_DTLS_STATE_CHANGE, + PLAINTRANSPORT_TUPLE, + PLAINTRANSPORT_RTCP_TUPLE, + DIRECTTRANSPORT_RTCP, + PRODUCER_SCORE, + PRODUCER_TRACE, + PRODUCER_VIDEO_ORIENTATION_CHANGE, + CONSUMER_PRODUCER_PAUSE, + CONSUMER_PRODUCER_RESUME, + CONSUMER_PRODUCER_CLOSE, + CONSUMER_LAYERS_CHANGE, + CONSUMER_RTP, + CONSUMER_SCORE, + CONSUMER_TRACE, + DATACONSUMER_BUFFERED_AMOUNT_LOW, + DATACONSUMER_SCTP_SENDBUFFER_FULL, + DATACONSUMER_DATAPRODUCER_CLOSE, + DATACONSUMER_MESSAGE, + ACTIVESPEAKEROBSERVER_DOMINANT_SPEAKER, + AUDIOLEVELOBSERVER_SILENCE, + AUDIOLEVELOBSERVER_VOLUMES, +} + +union Body { + // Notifications to worker. + FBS.Transport.SendRtcpNotification, + FBS.Transport.SctpStateChangeNotification, + FBS.Producer.SendNotification, + FBS.DataProducer.SendNotification, + // Notifications from worker. + FBS.Transport.TraceNotification, + FBS.WebRtcTransport.IceSelectedTupleChangeNotification, + FBS.WebRtcTransport.IceStateChangeNotification, + FBS.WebRtcTransport.DtlsStateChangeNotification, + FBS.PlainTransport.TupleNotification, + FBS.PlainTransport.RtcpTupleNotification, + FBS.DirectTransport.RtcpNotification, + FBS.Producer.ScoreNotification, + FBS.Producer.TraceNotification, + FBS.Producer.VideoOrientationChangeNotification, + FBS.Consumer.LayersChangeNotification, + FBS.Consumer.RtpNotification, + FBS.Consumer.ScoreNotification, + FBS.Consumer.TraceNotification, + FBS.DataConsumer.MessageNotification, + FBS.DataConsumer.BufferedAmountLowNotification, + FBS.ActiveSpeakerObserver.DominantSpeakerNotification, + FBS.AudioLevelObserver.VolumesNotification, +} + +table Notification { + handler_id:string; + event:Event; + body:Body; +} diff --git a/worker/fbs/pipeTransport.fbs b/worker/fbs/pipeTransport.fbs new file mode 100644 index 0000000000..d80e7204d5 --- /dev/null +++ b/worker/fbs/pipeTransport.fbs @@ -0,0 +1,33 @@ +include "transport.fbs"; + +namespace FBS.PipeTransport; + +table PipeTransportOptions { + base:FBS.Transport.Options (required); + listen_ip:FBS.Transport.ListenIp (required); + port:uint16; + enable_rtx:bool; + enable_srtp:bool; +} + +table ConnectRequest { + ip:string (required); + port:uint16 = null; + srtp_parameters:FBS.Transport.SrtpParameters; +} + +table ConnectResponse { + tuple:FBS.Transport.Tuple; +} + +table DumpResponse { + base:FBS.Transport.Dump (required); + tuple:FBS.Transport.Tuple (required); + rtx:bool; + srtp_parameters:FBS.Transport.SrtpParameters; +} + +table GetStatsResponse { + base:FBS.Transport.Stats (required); + tuple:FBS.Transport.Tuple (required); +} diff --git a/worker/fbs/plainTransport.fbs b/worker/fbs/plainTransport.fbs new file mode 100644 index 0000000000..152523b254 --- /dev/null +++ b/worker/fbs/plainTransport.fbs @@ -0,0 +1,54 @@ +include "transport.fbs"; +include "sctpParameters.fbs"; + +namespace FBS.PlainTransport; + +table PlainTransportOptions { + base:FBS.Transport.Options; + listen_ip:FBS.Transport.ListenIp (required); + port:uint16; + rtcp_mux:bool; + comedia:bool; + enable_srtp:bool; + srtp_crypto_suite:string; +} + +table ConnectRequest { + ip:string; + port:uint16 = null; + rtcp_port:uint16 = null; + srtp_parameters:FBS.Transport.SrtpParameters; +} + +table ConnectResponse { + tuple:FBS.Transport.Tuple (required); + rtcp_tuple:FBS.Transport.Tuple; + srtp_parameters:FBS.Transport.SrtpParameters; +} + +table DumpResponse { + base:FBS.Transport.Dump (required); + rtcp_mux:bool; + comedia:bool; + tuple:FBS.Transport.Tuple; + rtcp_tuple:FBS.Transport.Tuple; + srtp_parameters:FBS.Transport.SrtpParameters; +} + +table GetStatsResponse { + base:FBS.Transport.Stats (required); + rtcp_mux:bool; + comedia:bool; + tuple:FBS.Transport.Tuple (required); + rtcp_tuple:FBS.Transport.Tuple; +} + +// Notifications from Worker. + +table TupleNotification { + tuple:FBS.Transport.Tuple (required); +} + +table RtcpTupleNotification { + tuple:FBS.Transport.Tuple (required); +} diff --git a/worker/fbs/producer.fbs b/worker/fbs/producer.fbs new file mode 100644 index 0000000000..64d7d81ee2 --- /dev/null +++ b/worker/fbs/producer.fbs @@ -0,0 +1,79 @@ +include "rtpParameters.fbs"; +include "rtpStream.fbs"; + +namespace FBS.Producer; + +table EnableTraceEventRequest { + events:[string] (required); +} + +table DumpResponse { + id:string (required); + kind:FBS.RtpParameters.MediaKind; + type:string (required); + rtp_parameters:FBS.RtpParameters.RtpParameters (required); + rtp_mapping:FBS.RtpParameters.RtpMapping (required); + rtp_streams:[FBS.RtpStream.Dump]; + trace_event_types:[string] (required); + paused:bool = false; +} + +table GetStatsResponse { + stats:[FBS.RtpStream.Stats]; +} + +table SendNotification { + data:[uint8] (required); +} + +// Notifications from Worker. + +table Score { + ssrc:uint32; + rid:string; + score:uint8; +} + +table ScoreNotification { + scores:[Score]; +} + +table VideoOrientationChangeNotification { + camera:bool; + flip:bool; + rotation:uint16; +} + +enum TraceType: uint8 { KEYFRAME = 0, FIR, NACK, PLI, RTP, } +// NOTE (windows): IN|OUT are macros defined in windef.h. +enum TraceDirection: uint8 { DIRECTION_IN = 0, DIRECTION_OUT } + +union TraceInfo { + KeyFrameTraceInfo, + FirTraceInfo, + PliTraceInfo, + RtpTraceInfo, +} + +table KeyFrameTraceInfo { + is_rtx:bool; +} + +table FirTraceInfo { + ssrc:uint32; +} + +table PliTraceInfo { + ssrc:uint32; +} + +table RtpTraceInfo { + is_rtx:bool; +} + +table TraceNotification { + type: TraceType; + timestamp: uint64; + direction: TraceDirection; + info: TraceInfo; +} diff --git a/worker/fbs/request.fbs b/worker/fbs/request.fbs new file mode 100644 index 0000000000..58374d3e11 --- /dev/null +++ b/worker/fbs/request.fbs @@ -0,0 +1,122 @@ +include "worker.fbs"; +include "router.fbs"; +include "transport.fbs"; +include "producer.fbs"; +include "consumer.fbs"; +include "dataConsumer.fbs"; +include "rtpObserver.fbs"; + +namespace FBS.Request; + +enum Method: uint8 { + WORKER_CLOSE = 0, + WORKER_DUMP, + WORKER_GET_RESOURCE_USAGE, + WORKER_UPDATE_SETTINGS, + WORKER_CREATE_WEBRTC_SERVER, + WORKER_CREATE_ROUTER, + WORKER_WEBRTC_SERVER_CLOSE, + WORKER_CLOSE_ROUTER, + WEBRTC_SERVER_DUMP, + ROUTER_DUMP, + ROUTER_CREATE_WEBRTC_TRANSPORT, + ROUTER_CREATE_WEBRTC_TRANSPORT_WITH_SERVER, + ROUTER_CREATE_PLAIN_TRANSPORT, + ROUTER_CREATE_PIPE_TRANSPORT, + ROUTER_CREATE_DIRECT_TRANSPORT, + ROUTER_CLOSE_TRANSPORT, + ROUTER_CREATE_ACTIVE_SPEAKER_OBSERVER, + ROUTER_CREATE_AUDIO_LEVEL_OBSERVER, + ROUTER_CLOSE_RTP_OBSERVER, + TRANSPORT_DUMP, + TRANSPORT_GET_STATS, + TRANSPORT_CONNECT, + TRANSPORT_SET_MAX_INCOMING_BITRATE, + TRANSPORT_SET_MAX_OUTGOING_BITRATE, + TRANSPORT_SET_MIN_OUTGOING_BITRATE, + TRANSPORT_RESTART_ICE, + TRANSPORT_PRODUCE, + TRANSPORT_PRODUCE_DATA, + TRANSPORT_CONSUME, + TRANSPORT_CONSUME_DATA, + TRANSPORT_ENABLE_TRACE_EVENT, + TRANSPORT_CLOSE_PRODUCER, + TRANSPORT_CLOSE_CONSUMER, + TRANSPORT_CLOSE_DATA_PRODUCER, + TRANSPORT_CLOSE_DATA_CONSUMER, + PLAIN_TRANSPORT_CONNECT, + PIPE_TRANSPORT_CONNECT, + WEBRTC_TRANSPORT_CONNECT, + PRODUCER_DUMP, + PRODUCER_GET_STATS, + PRODUCER_PAUSE, + PRODUCER_RESUME, + PRODUCER_ENABLE_TRACE_EVENT, + CONSUMER_DUMP, + CONSUMER_GET_STATS, + CONSUMER_PAUSE, + CONSUMER_RESUME, + CONSUMER_SET_PREFERRED_LAYERS, + CONSUMER_SET_PRIORITY, + CONSUMER_REQUEST_KEY_FRAME, + CONSUMER_ENABLE_TRACE_EVENT, + DATA_PRODUCER_DUMP, + DATA_PRODUCER_GET_STATS, + DATA_CONSUMER_DUMP, + DATA_CONSUMER_GET_STATS, + DATA_CONSUMER_GET_BUFFERED_AMOUNT, + DATA_CONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD, + DATA_CONSUMER_SEND, + RTP_OBSERVER_PAUSE, + RTP_OBSERVER_RESUME, + RTP_OBSERVER_ADD_PRODUCER, + RTP_OBSERVER_REMOVE_PRODUCER, +} + +union Body { + FBS.Worker.UpdateSettingsRequest, + FBS.Worker.CreateWebRtcServerRequest, + FBS.Worker.CloseWebRtcServerRequest, + FBS.Worker.CreateRouterRequest, + FBS.Worker.CloseRouterRequest, + FBS.Router.CreateWebRtcTransportRequest, + FBS.Router.CreatePlainTransportRequest, + FBS.Router.CreatePipeTransportRequest, + FBS.Router.CreateDirectTransportRequest, + FBS.Router.CreateActiveSpeakerObserverRequest, + FBS.Router.CreateAudioLevelObserverRequest, + FBS.Router.CloseTransportRequest, + FBS.Router.CloseRtpObserverRequest, + FBS.Transport.SetMaxIncomingBitrateRequest, + FBS.Transport.SetMaxOutgoingBitrateRequest, + FBS.Transport.SetMinOutgoingBitrateRequest, + FBS.Transport.ProduceRequest, + FBS.Transport.ConsumeRequest, + FBS.Transport.ProduceDataRequest, + FBS.Transport.ConsumeDataRequest, + FBS.Transport.EnableTraceEventRequest, + FBS.Transport.CloseProducerRequest, + FBS.Transport.CloseConsumerRequest, + FBS.Transport.CloseDataProducerRequest, + FBS.Transport.CloseDataConsumerRequest, + FBS.PlainTransport.ConnectRequest, + FBS.PipeTransport.ConnectRequest, + FBS.WebRtcTransport.ConnectRequest, + FBS.Producer.EnableTraceEventRequest, + FBS.Consumer.SetPreferredLayersRequest, + FBS.Consumer.SetPriorityRequest, + FBS.Consumer.EnableTraceEventRequest, + FBS.DataConsumer.SetBufferedAmountLowThresholdRequest, + FBS.DataConsumer.SendRequest, + FBS.RtpObserver.AddProducerRequest, + FBS.RtpObserver.RemoveProducerRequest, +} + +table Request { + id:uint32; + method:Method; + handler_id:string; + body:Body; +} + +root_type Request; diff --git a/worker/fbs/response.fbs b/worker/fbs/response.fbs new file mode 100644 index 0000000000..bd94fbe2db --- /dev/null +++ b/worker/fbs/response.fbs @@ -0,0 +1,50 @@ +include "worker.fbs"; +include "router.fbs"; +include "webRtcServer.fbs"; +include "transport.fbs"; +include "producer.fbs"; +include "consumer.fbs"; +include "dataProducer.fbs"; +include "dataConsumer.fbs"; + +namespace FBS.Response; + +union Body { + FBS_Worker_DumpResponse: FBS.Worker.DumpResponse, + FBS_Worker_ResourceUsageResponse: FBS.Worker.ResourceUsageResponse, + FBS_WebRtcServer_DumpResponse: FBS.WebRtcServer.DumpResponse, + FBS_Router_DumpResponse: FBS.Router.DumpResponse, + FBS_Transport_ProduceResponse: FBS.Transport.ProduceResponse, + FBS_Transport_ConsumeResponse: FBS.Transport.ConsumeResponse, + FBS_Transport_RestartIceResponse: FBS.Transport.RestartIceResponse, + FBS_PlainTransport_ConnectResponse: FBS.PlainTransport.ConnectResponse, + FBS_PlainTransport_DumpResponse: FBS.PlainTransport.DumpResponse, + FBS_PlainTransport_GetStatsResponse: FBS.PlainTransport.GetStatsResponse, + FBS_PipeTransport_ConnectResponse: FBS.PipeTransport.ConnectResponse, + FBS_PipeTransport_DumpResponse: FBS.PipeTransport.DumpResponse, + FBS_PipeTransport_GetStatsResponse: FBS.PipeTransport.GetStatsResponse, + FBS_DirectTransport_DumpResponse: FBS.DirectTransport.DumpResponse, + FBS_DirectTransport_GetStatsResponse: FBS.DirectTransport.GetStatsResponse, + FBS_WebRtcTransport_ConnectResponse: FBS.WebRtcTransport.ConnectResponse, + FBS_WebRtcTransport_DumpResponse: FBS.WebRtcTransport.DumpResponse, + FBS_WebRtcTransport_GetStatsResponse: FBS.WebRtcTransport.GetStatsResponse, + FBS_Producer_DumpResponse: FBS.Producer.DumpResponse, + FBS_Producer_GetStatsResponse: FBS.Producer.GetStatsResponse, + FBS_Consumer_DumpResponse: FBS.Consumer.DumpResponse, + FBS_Consumer_GetStatsResponse: FBS.Consumer.GetStatsResponse, + FBS_Consumer_SetPreferredLayersResponse: FBS.Consumer.SetPreferredLayersResponse, + FBS_Consumer_SetPriorityResponse: FBS.Consumer.SetPriorityResponse, + FBS_DataProducer_DumpResponse: FBS.DataProducer.DumpResponse, + FBS_DataProducer_GetStatsResponse: FBS.DataProducer.GetStatsResponse, + FBS_DataConsumer_GetBufferedAmountResponse: FBS.DataConsumer.GetBufferedAmountResponse, + FBS_DataConsumer_DumpResponse: FBS.DataConsumer.DumpResponse, + FBS_DataConsumer_GetStatsResponse: FBS.DataConsumer.GetStatsResponse, +} + +table Response { + id:uint32; + accepted:bool; + body:Body; + error:string; + reason:string; +} diff --git a/worker/fbs/router.fbs b/worker/fbs/router.fbs new file mode 100644 index 0000000000..ec204dddef --- /dev/null +++ b/worker/fbs/router.fbs @@ -0,0 +1,59 @@ +include "common.fbs"; +include "activeSpeakerObserver.fbs"; +include "audioLevelObserver.fbs"; +include "transport.fbs"; +include "pipeTransport.fbs"; +include "plainTransport.fbs"; +include "webRtcTransport.fbs"; +include "directTransport.fbs"; + +namespace FBS.Router; + +table DumpResponse { + id:string (required); + transport_ids:[string]; + rtp_observer_ids:[string]; + map_producer_id_consumer_ids:[FBS.Common.StringStringArray]; + map_consumer_id_producer_id:[FBS.Common.StringString]; + map_producer_id_observer_ids:[FBS.Common.StringStringArray]; + map_data_producer_id_data_consumer_ids:[FBS.Common.StringStringArray]; + map_data_consumer_id_data_producer_id:[FBS.Common.StringString]; +} + +table CreatePipeTransportRequest { + transport_id:string (required); + options:FBS.PipeTransport.PipeTransportOptions (required); +} + +table CreatePlainTransportRequest { + transport_id:string (required); + options:FBS.PlainTransport.PlainTransportOptions (required); +} + +table CreateWebRtcTransportRequest { + transport_id:string (required); + options:FBS.WebRtcTransport.WebRtcTransportOptions (required); +} + +table CreateDirectTransportRequest { + transport_id:string (required); + options:FBS.DirectTransport.DirectTransportOptions (required); +} + +table CreateAudioLevelObserverRequest { + rtp_observer_id:string (required); + options:FBS.AudioLevelObserver.AudioLevelObserverOptions (required); +} + +table CreateActiveSpeakerObserverRequest { + active_speaker_observer_id:string (required); + options:FBS.ActiveSpeakerObserver.ActiveSpeakerObserverOptions (required); +} + +table CloseTransportRequest { + transport_id:string (required); +} + +table CloseRtpObserverRequest { + rtp_observer_id:string (required); +} diff --git a/worker/fbs/rtpObserver.fbs b/worker/fbs/rtpObserver.fbs new file mode 100644 index 0000000000..b3f754f670 --- /dev/null +++ b/worker/fbs/rtpObserver.fbs @@ -0,0 +1,10 @@ + +namespace FBS.RtpObserver; + +table AddProducerRequest { + producer_id:string (required); +} + +table RemoveProducerRequest { + producer_id:string (required); +} diff --git a/worker/fbs/rtpParameters.fbs b/worker/fbs/rtpParameters.fbs new file mode 100644 index 0000000000..d9c624e7c5 --- /dev/null +++ b/worker/fbs/rtpParameters.fbs @@ -0,0 +1,104 @@ + +namespace FBS.RtpParameters; + +enum MediaKind : uint8 { ALL = 0, AUDIO, VIDEO } +enum Type: uint8 { NONE = 0, SIMPLE, SIMULCAST, SVC, PIPE } + +// Boolean is a uint8/byte type. +table Boolean { + value:uint8; +} + +table Integer { + value:int32; +} + +table IntegerArray { + value:[int32]; +} + +table Double { + value:double; +} + +table String { + value:string; +} + +union Value { + Boolean, + Integer, + Double, + String, + IntegerArray, +} + +table Parameter { + name: string (required); + value: Value; +} + +table RtcpFeedback { + type:string (required); + parameter:string; +} + +table RtpCodecParameters { + mime_type:string (required); + payload_type:uint8; + clock_rate:uint32; + channels:uint8 = null; + parameters:[Parameter]; + rtcp_feedback:[RtcpFeedback]; +} + +table RtpHeaderExtensionParameters { + uri:string (required); + id:uint8; + encrypt:bool = false; + parameters:[Parameter]; +} + +table Rtx { + ssrc:uint32; +} + +table RtpEncodingParameters { + ssrc:uint32 = null; + rid:string; + codec_payload_type:uint8 = null; + rtx:Rtx; + dtx:bool = false; + scalability_mode:string; + max_bitrate:uint32 = null; +} + +table RtcpParameters { + cname:string; + reduced_size:bool = true; +} + +table RtpParameters { + mid:string; + codecs:[RtpCodecParameters] (required); + header_extensions:[RtpHeaderExtensionParameters]; + encodings:[RtpEncodingParameters]; + rtcp:RtcpParameters; +} + +table CodecMapping { + payload_type:uint8; + mapped_payload_type:uint8; +} + +table EncodingMapping { + rid:string; + ssrc:uint32 = null; + scalability_mode:string; + mapped_ssrc:uint32; +} + +table RtpMapping { + codecs:[CodecMapping] (required); + encodings:[EncodingMapping] (required); +} diff --git a/worker/fbs/rtpStream.fbs b/worker/fbs/rtpStream.fbs new file mode 100644 index 0000000000..f12187ca5c --- /dev/null +++ b/worker/fbs/rtpStream.fbs @@ -0,0 +1,81 @@ +include "rtpParameters.fbs"; +include "rtxStream.fbs"; + +namespace FBS.RtpStream; + +table Params { + encoding_idx:uint32; + ssrc:uint32; + payload_type:uint8; + mime_type:string (required); + clock_rate: uint32; + rid:string; + cname:string (required); + rtx_ssrc:uint32 = null; + rtx_payload_type:uint8 = null; + use_nack:bool; + use_pli:bool; + use_fir:bool; + use_in_band_fec:bool; + use_dtx:bool; + spatial_layers:uint8; + temporal_layers:uint8; +} + +table Dump { + params:Params (required); + score:uint8; + rtx_stream:FBS.RtxStream.RtxDump; +} + +table BitrateByLayer { + layer:string (required); + bitrate:uint64; +} + +union StatsData { + BaseStats, + RecvStats, + SendStats, +} + +table Stats { + data:StatsData; +} + +table BaseStats { + timestamp:uint64; + ssrc:uint32; + kind:FBS.RtpParameters.MediaKind; + mime_type:string (required); + packets_lost:uint64; + fraction_lost:uint64; + packets_discarded:uint64; + packets_retransmitted:uint64; + packets_repaired:uint64; + nack_count:uint64; + nack_packet_count:uint64; + pli_count:uint64; + fir_count:uint64; + score:uint8; + rid:string; + rtx_ssrc:uint32 = null; + rtx_packets_discarded:uint64; + round_trip_time:float; +} + +table RecvStats { + base:Stats (required); + jitter:uint32; + packet_count:uint64; + byte_count:uint64; + bitrate:uint64; + bitrate_by_layer:[BitrateByLayer]; +} + +table SendStats { + base:Stats (required); + packet_count:uint64; + byte_count:uint64; + bitrate:uint64; +} diff --git a/worker/fbs/rtxStream.fbs b/worker/fbs/rtxStream.fbs new file mode 100644 index 0000000000..9e96efc568 --- /dev/null +++ b/worker/fbs/rtxStream.fbs @@ -0,0 +1,16 @@ + +namespace FBS.RtxStream; + +table Params { + ssrc:uint32; + payload_type:uint8; + mime_type:string (required); + clock_rate: uint32; + rrid:string; + cname:string (required); +} + +// NOTE: Naming this Dump collides in TS generation for Producer.DumpResponse. +table RtxDump { + params:Params (required); +} diff --git a/worker/fbs/sctpAssociation.fbs b/worker/fbs/sctpAssociation.fbs new file mode 100644 index 0000000000..ef5e0b17d6 --- /dev/null +++ b/worker/fbs/sctpAssociation.fbs @@ -0,0 +1,11 @@ + +namespace FBS.SctpAssociation; + +enum SctpState: uint8 { + NEW = 0, + CONNECTING, + CONNECTED, + FAILED, + CLOSED, +} + diff --git a/worker/fbs/sctpParameters.fbs b/worker/fbs/sctpParameters.fbs new file mode 100644 index 0000000000..ffbd8b7181 --- /dev/null +++ b/worker/fbs/sctpParameters.fbs @@ -0,0 +1,25 @@ + +namespace FBS.SctpParameters; + +table NumSctpStreams { + os:uint32 = 1024; + mis:uint32 = 1024; +} + +table SctpParameters { + // Port is always 5000. + port:uint16=5000; + os:uint16; + mis:uint16; + max_message_size:uint32; + send_buffer_size:uint32; + sctp_buffered_amount:uint32; + is_data_channel:bool; +} + +table SctpStreamParameters { + stream_id:uint16; + ordered:bool = null; + max_packet_life_time:uint16 = null; + max_retransmits:uint16 = null; +} diff --git a/worker/fbs/transport.fbs b/worker/fbs/transport.fbs new file mode 100644 index 0000000000..c961a3f604 --- /dev/null +++ b/worker/fbs/transport.fbs @@ -0,0 +1,220 @@ +include "common.fbs"; +include "consumer.fbs"; +include "rtpParameters.fbs"; +include "sctpAssociation.fbs"; +include "sctpParameters.fbs"; + +namespace FBS.Transport; + +enum Protocol: uint8 { UDP = 1, TCP } + +table ListenIp { + ip:string (required); + announced_ip:string; +} + +table RestartIceResponse { + username_fragment:string (required); + password:string (required); + ice_lite:bool; +} + +table ConsumeRequest { + consumer_id:string (required); + producer_id:string (required); + kind:FBS.RtpParameters.MediaKind; + rtp_parameters:FBS.RtpParameters.RtpParameters (required); + type:FBS.RtpParameters.Type; + consumable_rtp_encodings:[FBS.RtpParameters.RtpEncodingParameters] (required); + paused:bool = false; + preferred_layers:FBS.Consumer.ConsumerLayers; + ignore_dtx:bool = false; +} + +table ConsumeResponse { + paused:bool; + producer_paused:bool; + score:FBS.Consumer.ConsumerScore; + preferred_layers:FBS.Consumer.ConsumerLayers; +} + +table ProduceRequest { + producer_id:string (required); + kind:FBS.RtpParameters.MediaKind; + rtp_parameters:FBS.RtpParameters.RtpParameters (required); + rtp_mapping:FBS.RtpParameters.RtpMapping (required); + key_frame_request_delay:uint16; + paused:bool = false; +} + +table ProduceResponse { + type:FBS.RtpParameters.Type; +} + +table ProduceDataRequest { + data_producer_id:string (required); + type:string (required); + sctp_stream_parameters:FBS.SctpParameters.SctpStreamParameters; + label:string; + protocol:string; +} + +table ConsumeDataRequest { + data_consumer_id:string (required); + data_producer_id:string (required); + type:string (required); + sctp_stream_parameters:FBS.SctpParameters.SctpStreamParameters; + label:string; + protocol:string; +} + +table Tuple { + local_ip:string (required); + local_port:uint16; + remote_ip:string (required); + remote_port:uint16; + protocol:string (required); +} + +table SrtpParameters { + crypto_suite:string (required); + key_base64:string (required); +} + +table RtpListener { + ssrc_table:[FBS.Common.Uint32String] (required); + mid_table:[FBS.Common.StringString] (required); + rid_table:[FBS.Common.StringString] (required); +} + +table SctpListener { + stream_id_table:[FBS.Common.Uint16String] (required); +} + +table Dump { + id:string (required); + direct:bool=false; + producer_ids:[string] (required); + consumer_ids:[string] (required); + map_ssrc_consumer_id:[FBS.Common.Uint32String] (required); + map_rtx_ssrc_consumer_id:[FBS.Common.Uint32String] (required); + data_producer_ids:[string] (required); + data_consumer_ids:[string] (required); + recv_rtp_header_extensions:[FBS.Common.StringUint8] (required); + rtp_listener:RtpListener (required); + max_message_size:uint32; + sctp_parameters:FBS.SctpParameters.SctpParameters; + sctp_state:string; + sctp_listener: SctpListener; + trace_event_types:[string] (required); +} + +table Options { + direct:bool = false; + max_message_size:uint32; + initial_available_outgoing_bitrate:uint32; + enable_sctp:bool = false; + num_sctp_streams:FBS.SctpParameters.NumSctpStreams; + max_sctp_message_size:uint32; + sctp_send_buffer_size:uint32; + is_data_channel:bool = false; +} + +table Stats { + transport_id:string (required); + timestamp:uint64; + sctp_state:string; + bytes_received:uint64; + recv_bitrate:uint64; + bytes_sent:uint64; + send_bitrate:uint64; + rtp_bytes_received:uint64; + rtp_recv_bitrate:uint64; + rtp_bytes_sent:uint64; + rtp_send_bitrate:uint64; + rtx_bytes_received:uint64; + rtx_recv_bitrate:uint64; + rtx_bytes_sent:uint64; + rtx_send_bitrate:uint64; + probation_bytes_sent:uint64; + probation_send_bitrate:uint64; + available_outgoing_bitrate:uint64; + available_incoming_bitrate:uint64; + max_incoming_bitrate:uint64; + max_outgoing_bitrate:uint64; + min_outgoing_bitrate:uint64; + rtp_packet_loss_received:uint64; + rtp_packet_loss_sent:uint64; +} + +table SetMaxIncomingBitrateRequest { + max_incoming_bitrate:uint32; +} + +table SetMaxOutgoingBitrateRequest { + max_outgoing_bitrate:uint32; +} + +table SetMinOutgoingBitrateRequest { + min_outgoing_bitrate:uint32; +} + +table EnableTraceEventRequest { + events:[string] (required); +} + +table CloseProducerRequest { + producer_id:string (required); +} + +table CloseConsumerRequest { + consumer_id:string (required); +} + +table CloseDataProducerRequest { + data_producer_id:string (required); +} + +table CloseDataConsumerRequest { + data_consumer_id:string (required); +} + +// Notifications to Worker. + +table SendRtcpNotification { + data:[uint8] (required); +} + +// Notifications from Worker. + +table SctpStateChangeNotification { + sctp_state:FBS.SctpAssociation.SctpState; +} + +enum TraceType: uint8 { PROBATION = 0, BWE } +// NOTE (windows): IN|OUT are macros defined in windef.h. +enum TraceDirection: uint8 { DIRECTION_IN = 0, DIRECTION_OUT } + +union TraceInfo { + BweTraceInfo, +} + +enum BweType: uint8 { TRANSPORT_CC = 0, REMB } + +table BweTraceInfo { + desired_bitrate:uint32; + effective_desired_bitrate:uint32; + min_bitrate:uint32; + max_bitrate:uint32; + start_bitrate:uint32; + max_padding_bitrate:uint32; + available_bitrate:uint32; + bwe_type:BweType; +} + +table TraceNotification { + type: TraceType; + timestamp: uint64; + direction: TraceDirection; + info: TraceInfo; +} diff --git a/worker/fbs/webRtcServer.fbs b/worker/fbs/webRtcServer.fbs new file mode 100644 index 0000000000..087f744088 --- /dev/null +++ b/worker/fbs/webRtcServer.fbs @@ -0,0 +1,34 @@ +include "transport.fbs"; + +namespace FBS.WebRtcServer; + +table ListenInfo { + protocol:FBS.Transport.Protocol=UDP; + ip:string (required); + announced_ip:string; + port:uint16 = 0; +} + +table IpPort { + ip:string (required); + port:uint16; +} + +table IceUserNameFragment { + local_ice_username_fragment:string (required); + web_rtc_transport_id:string (required); +} + +table TupleHash { + local_ice_username_fragment:uint64; + web_rtc_transport_id:string (required); +} + +table DumpResponse { + id:string (required); + udp_sockets:[IpPort]; + tcp_servers:[IpPort]; + web_rtc_transport_ids:[string]; + local_ice_username_fragments:[IceUserNameFragment]; + tuple_hashes:[TupleHash]; +} diff --git a/worker/fbs/webRtcTransport.fbs b/worker/fbs/webRtcTransport.fbs new file mode 100644 index 0000000000..2fcaa930fc --- /dev/null +++ b/worker/fbs/webRtcTransport.fbs @@ -0,0 +1,98 @@ +include "transport.fbs"; +include "sctpParameters.fbs"; + +namespace FBS.WebRtcTransport; + +table ListenIndividual { + listen_ips:[FBS.Transport.ListenIp] (required); + port:uint16; +} + +table ListenServer { + web_rtc_server_id:string (required); +} + +union Listen { + ListenIndividual, + ListenServer, +} + +table WebRtcTransportOptions { + base:FBS.Transport.Options (required); + listen:Listen (required); + enable_udp:bool = true; + enable_tcp:bool = false; + prefer_udp:bool = false; + prefer_tcp:bool = false; +} + +table Fingerprint { + algorithm:string (required); + value:string (required); +} + +table DtlsParameters { + fingerprints:[Fingerprint] (required); + role:string; +} + +table IceParameters { + username_fragment:string (required); + password:string (required); + ice_lite:bool = true; +} + +table IceCandidate { + foundation:string (required); + priority:uint32; + ip:string (required); + protocol:string (required); + port:uint16; + type:string; + tcp_type:string; +} + +table ConnectRequest { + dtls_parameters:DtlsParameters (required); +} + +table ConnectResponse { + dtls_local_role:string (required); +} + +table DumpResponse { + base:FBS.Transport.Dump (required); + ice_role:string (required); + ice_parameters:IceParameters (required); + ice_candidates:[IceCandidate] (required); + ice_state:string (required); + ice_selected_tuple:FBS.Transport.Tuple; + dtls_parameters:DtlsParameters (required); + dtls_state:string (required); +} + +table GetStatsResponse { + base:FBS.Transport.Stats (required); + ice_role:string (required); + ice_state:string (required); + ice_selected_tuple:FBS.Transport.Tuple; + dtls_state:string (required); +} + +// Notifications from Worker. + +table IceSelectedTupleChangeNotification { + tuple:FBS.Transport.Tuple (required); +} + +enum IceState: uint8 { NEW = 0, CONNECTED, COMPLETED, DISCONNECTED, CLOSED } +enum DtlsState: uint8 { NEW = 0, CONNECTING, CONNECTED, FAILED, CLOSED } + +table IceStateChangeNotification { + ice_state:IceState; +} + +table DtlsStateChangeNotification { + dtls_state:DtlsState; + remote_cert:string; +} diff --git a/worker/fbs/worker.fbs b/worker/fbs/worker.fbs new file mode 100644 index 0000000000..26b97b1437 --- /dev/null +++ b/worker/fbs/worker.fbs @@ -0,0 +1,56 @@ +include "webRtcServer.fbs"; + +namespace FBS.Worker; + +table ChannelMessageHandlers { + channel_request_handlers:[string]; + channel_notification_handlers:[string]; +} + +table DumpResponse { + pid:uint32; + web_rtc_server_ids:[string]; + router_ids:[string]; + channel_message_handlers:ChannelMessageHandlers; +} + +table ResourceUsageResponse { + ru_utime:uint64; + ru_stime:uint64; + ru_maxrss:uint64; + ru_ixrss:uint64; + ru_idrss:uint64; + ru_isrss:uint64; + ru_minflt:uint64; + ru_majflt:uint64; + ru_nswap:uint64; + ru_inblock:uint64; + ru_oublock:uint64; + ru_msgsnd:uint64; + ru_msgrcv:uint64; + ru_nsignals:uint64; + ru_nvcsw:uint64; + ru_nivcsw:uint64; +} + +table UpdateSettingsRequest { + log_level:string; + log_tags:[string]; +} + +table CreateWebRtcServerRequest { + web_rtc_server_id:string (required); + listen_infos:[FBS.WebRtcServer.ListenInfo]; +} + +table CloseWebRtcServerRequest { + web_rtc_server_id:string (required); +} + +table CreateRouterRequest { + router_id:string (required); +} + +table CloseRouterRequest { + router_id:string (required); +} diff --git a/worker/include/Channel/ChannelNotification.hpp b/worker/include/Channel/ChannelNotification.hpp new file mode 100644 index 0000000000..05fdf7d290 --- /dev/null +++ b/worker/include/Channel/ChannelNotification.hpp @@ -0,0 +1,33 @@ +#ifndef MS_CHANNEL_NOTIFICATION_HPP +#define MS_CHANNEL_NOTIFICATION_HPP + +#include "common.hpp" +#include "FBS/notification_generated.h" +#include +#include + +namespace Channel +{ + class ChannelNotification + { + public: + using Event = FBS::Notification::Event; + + private: + static absl::flat_hash_map event2String; + + public: + explicit ChannelNotification(const FBS::Notification::Notification* notification); + ~ChannelNotification() = default; + + public: + // Passed by argument. + Event event; + // Others. + const char* eventCStr; + std::string handlerId; + const FBS::Notification::Notification* data{ nullptr }; + }; +} // namespace Channel + +#endif diff --git a/worker/include/Channel/ChannelNotifier.hpp b/worker/include/Channel/ChannelNotifier.hpp index 5f3eabf5be..c918b077a3 100644 --- a/worker/include/Channel/ChannelNotifier.hpp +++ b/worker/include/Channel/ChannelNotifier.hpp @@ -3,11 +3,8 @@ #include "common.hpp" #include "Channel/ChannelSocket.hpp" -#include #include -using json = nlohmann::json; - namespace Channel { class ChannelNotifier @@ -16,14 +13,56 @@ namespace Channel explicit ChannelNotifier(Channel::ChannelSocket* channel); public: - void Emit(uint64_t targetId, const char* event); - void Emit(const std::string& targetId, const char* event); - void Emit(const std::string& targetId, const char* event, json& data); - void Emit(const std::string& targetId, const char* event, const std::string& data); + flatbuffers::FlatBufferBuilder& GetBufferBuilder() + { + return this->bufferBuilder; + } + + template + void Emit( + const std::string& targetId, + FBS::Notification::Event event, + FBS::Notification::Body type, + flatbuffers::Offset& body) + { + auto& builder = ChannelNotifier::bufferBuilder; + auto notification = FBS::Notification::CreateNotificationDirect( + builder, targetId.c_str(), event, type, body.Union()); + + auto message = FBS::Message::CreateMessage( + builder, + FBS::Message::Type::NOTIFICATION, + FBS::Message::Body::FBS_Notification_Notification, + notification.Union()); + + builder.FinishSizePrefixed(message); + this->channel->Send(builder.GetBufferPointer(), builder.GetSize()); + builder.Reset(); + } + + void Emit(const std::string& targetId, FBS::Notification::Event event) + { + auto& builder = ChannelNotifier::bufferBuilder; + auto notification = + FBS::Notification::CreateNotificationDirect(builder, targetId.c_str(), event); + + auto message = FBS::Message::CreateMessage( + builder, + FBS::Message::Type::NOTIFICATION, + FBS::Message::Body::FBS_Notification_Notification, + notification.Union()); + + builder.FinishSizePrefixed(message); + this->channel->Send(builder.GetBufferPointer(), builder.GetSize()); + builder.Reset(); + } + void Emit(const FBS::Notification::Notification& notification); private: // Passed by argument. Channel::ChannelSocket* channel{ nullptr }; + // Others. + flatbuffers::FlatBufferBuilder bufferBuilder{}; }; } // namespace Channel diff --git a/worker/include/Channel/ChannelRequest.hpp b/worker/include/Channel/ChannelRequest.hpp index 7381c94d7e..c26d20690c 100644 --- a/worker/include/Channel/ChannelRequest.hpp +++ b/worker/include/Channel/ChannelRequest.hpp @@ -2,12 +2,13 @@ #define MS_CHANNEL_REQUEST_HPP #include "common.hpp" +#include "FBS/message_generated.h" +#include "FBS/request_generated.h" +#include "FBS/response_generated.h" #include -#include +#include #include -using json = nlohmann::json; - namespace Channel { // Avoid cyclic #include problem by declaring classes instead of including @@ -17,89 +18,57 @@ namespace Channel class ChannelRequest { public: - enum class MethodId - { - WORKER_CLOSE = 1, - WORKER_DUMP, - WORKER_GET_RESOURCE_USAGE, - WORKER_UPDATE_SETTINGS, - WORKER_CREATE_WEBRTC_SERVER, - WORKER_CREATE_ROUTER, - WORKER_WEBRTC_SERVER_CLOSE, - WEBRTC_SERVER_DUMP, - WORKER_CLOSE_ROUTER, - ROUTER_DUMP, - ROUTER_CREATE_WEBRTC_TRANSPORT, - ROUTER_CREATE_WEBRTC_TRANSPORT_WITH_SERVER, - ROUTER_CREATE_PLAIN_TRANSPORT, - ROUTER_CREATE_PIPE_TRANSPORT, - ROUTER_CREATE_DIRECT_TRANSPORT, - ROUTER_CLOSE_TRANSPORT, - ROUTER_CREATE_ACTIVE_SPEAKER_OBSERVER, - ROUTER_CREATE_AUDIO_LEVEL_OBSERVER, - ROUTER_CLOSE_RTP_OBSERVER, - TRANSPORT_DUMP, - TRANSPORT_GET_STATS, - TRANSPORT_CONNECT, - TRANSPORT_SET_MAX_INCOMING_BITRATE, - TRANSPORT_SET_MAX_OUTGOING_BITRATE, - TRANSPORT_SET_MIN_OUTGOING_BITRATE, - TRANSPORT_RESTART_ICE, - TRANSPORT_PRODUCE, - TRANSPORT_CONSUME, - TRANSPORT_PRODUCE_DATA, - TRANSPORT_CONSUME_DATA, - TRANSPORT_ENABLE_TRACE_EVENT, - TRANSPORT_CLOSE_PRODUCER, - PRODUCER_DUMP, - PRODUCER_GET_STATS, - PRODUCER_PAUSE, - PRODUCER_RESUME, - PRODUCER_ENABLE_TRACE_EVENT, - TRANSPORT_CLOSE_CONSUMER, - CONSUMER_DUMP, - CONSUMER_GET_STATS, - CONSUMER_PAUSE, - CONSUMER_RESUME, - CONSUMER_SET_PREFERRED_LAYERS, - CONSUMER_SET_PRIORITY, - CONSUMER_REQUEST_KEY_FRAME, - CONSUMER_ENABLE_TRACE_EVENT, - TRANSPORT_CLOSE_DATA_PRODUCER, - DATA_PRODUCER_DUMP, - DATA_PRODUCER_GET_STATS, - TRANSPORT_CLOSE_DATA_CONSUMER, - DATA_CONSUMER_DUMP, - DATA_CONSUMER_GET_STATS, - DATA_CONSUMER_GET_BUFFERED_AMOUNT, - DATA_CONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD, - RTP_OBSERVER_PAUSE, - RTP_OBSERVER_RESUME, - RTP_OBSERVER_ADD_PRODUCER, - RTP_OBSERVER_REMOVE_PRODUCER - }; + using Method = FBS::Request::Method; - private: - static absl::flat_hash_map string2MethodId; + public: + static absl::flat_hash_map method2String; public: - ChannelRequest(Channel::ChannelSocket* channel, const char* msg, size_t msgLen); - virtual ~ChannelRequest(); + ChannelRequest(Channel::ChannelSocket* channel, const FBS::Request::Request* request); + ~ChannelRequest() = default; + flatbuffers::FlatBufferBuilder& GetBufferBuilder() + { + return this->bufferBuilder; + } void Accept(); - void Accept(json& data); + template + void Accept(FBS::Response::Body type, flatbuffers::Offset& body) + { + assert(!this->replied); + + this->replied = true; + + auto& builder = this->bufferBuilder; + auto response = FBS::Response::CreateResponse(builder, this->id, true, type, body.Union()); + + auto message = FBS::Message::CreateMessage( + builder, + FBS::Message::Type::RESPONSE, + FBS::Message::Body::FBS_Response_Response, + response.Union()); + + builder.FinishSizePrefixed(message); + this->Send(builder.GetBufferPointer(), builder.GetSize()); + builder.Reset(); + } void Error(const char* reason = nullptr); void TypeError(const char* reason = nullptr); + private: + void Send(uint8_t* buffer, size_t size); + void SendResponse(const flatbuffers::Offset& response); + public: // Passed by argument. Channel::ChannelSocket* channel{ nullptr }; + const FBS::Request::Request* data{ nullptr }; + // Others. + flatbuffers::FlatBufferBuilder bufferBuilder{}; uint32_t id{ 0u }; - std::string method; - MethodId methodId; + Method method; + const char* methodCStr; std::string handlerId; - json data; - // Others. bool replied{ false }; }; } // namespace Channel diff --git a/worker/include/Channel/ChannelSocket.hpp b/worker/include/Channel/ChannelSocket.hpp index fdc98b8e7e..58dc41a176 100644 --- a/worker/include/Channel/ChannelSocket.hpp +++ b/worker/include/Channel/ChannelSocket.hpp @@ -2,13 +2,11 @@ #define MS_CHANNEL_SOCKET_HPP #include "common.hpp" +#include "Channel/ChannelNotification.hpp" #include "Channel/ChannelRequest.hpp" #include "handles/UnixStreamSocket.hpp" -#include #include -using json = nlohmann::json; - namespace Channel { class ConsumerSocket : public ::UnixStreamSocket @@ -65,7 +63,16 @@ namespace Channel virtual void HandleRequest(Channel::ChannelRequest* request) = 0; }; - class Listener : public RequestHandler + class NotificationHandler + { + public: + virtual ~NotificationHandler() = default; + + public: + virtual void HandleNotification(Channel::ChannelNotification* notification) = 0; + }; + + class Listener : public RequestHandler, public NotificationHandler { public: virtual ~Listener() = default; @@ -86,8 +93,7 @@ namespace Channel public: void Close(); void SetListener(Listener* listener); - void Send(json& jsonMessage); - void Send(const std::string& message); + void Send(const uint8_t* message, uint32_t messageLen); void SendLog(const char* message, uint32_t messageLen); bool CallbackRead(); @@ -111,7 +117,7 @@ namespace Channel ChannelWriteFn channelWriteFn{ nullptr }; ChannelWriteCtx channelWriteCtx{ nullptr }; uv_async_t* uvReadHandle{ nullptr }; - uint8_t* writeBuffer{ nullptr }; + flatbuffers::FlatBufferBuilder bufferBuilder{}; }; } // namespace Channel diff --git a/worker/include/ChannelMessageRegistrator.hpp b/worker/include/ChannelMessageRegistrator.hpp index f01300a658..f27e708ff1 100644 --- a/worker/include/ChannelMessageRegistrator.hpp +++ b/worker/include/ChannelMessageRegistrator.hpp @@ -3,9 +3,7 @@ #include "common.hpp" #include "Channel/ChannelSocket.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" #include -#include #include class ChannelMessageRegistrator @@ -15,25 +13,19 @@ class ChannelMessageRegistrator ~ChannelMessageRegistrator(); public: - void FillJson(json& jsonObject); + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder); void RegisterHandler( const std::string& id, Channel::ChannelSocket::RequestHandler* channelRequestHandler, - PayloadChannel::PayloadChannelSocket::RequestHandler* payloadChannelRequestHandler, - PayloadChannel::PayloadChannelSocket::NotificationHandler* payloadChannelNotificationHandler); + Channel::ChannelSocket::NotificationHandler* channelNotificationHandler); void UnregisterHandler(const std::string& id); Channel::ChannelSocket::RequestHandler* GetChannelRequestHandler(const std::string& id); - PayloadChannel::PayloadChannelSocket::RequestHandler* GetPayloadChannelRequestHandler( - const std::string& id); - PayloadChannel::PayloadChannelSocket::NotificationHandler* GetPayloadChannelNotificationHandler( - const std::string& id); + Channel::ChannelSocket::NotificationHandler* GetChannelNotificationHandler(const std::string& id); private: absl::flat_hash_map mapChannelRequestHandlers; - absl::flat_hash_map - mapPayloadChannelRequestHandlers; - absl::flat_hash_map - mapPayloadChannelNotificationHandlers; + absl::flat_hash_map mapChannelNotificationHandlers; }; #endif diff --git a/worker/include/PayloadChannel/PayloadChannelNotification.hpp b/worker/include/PayloadChannel/PayloadChannelNotification.hpp deleted file mode 100644 index 5f4f3c2f86..0000000000 --- a/worker/include/PayloadChannel/PayloadChannelNotification.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef MS_PAYLOAD_CHANNEL_NOTIFICATION_HPP -#define MS_PAYLOAD_CHANNEL_NOTIFICATION_HPP - -#include "common.hpp" -#include -#include - -namespace PayloadChannel -{ - class PayloadChannelNotification - { - public: - enum class EventId - { - TRANSPORT_SEND_RTCP = 1, - PRODUCER_SEND, - DATA_PRODUCER_SEND - }; - - public: - static bool IsNotification(const char* msg, size_t msgLen); - - private: - static absl::flat_hash_map string2EventId; - - public: - PayloadChannelNotification(const char* msg, size_t msgLen); - virtual ~PayloadChannelNotification(); - - public: - void SetPayload(const uint8_t* payload, size_t payloadLen); - - public: - // Passed by argument. - std::string event; - EventId eventId; - std::string handlerId; - std::string data; - const uint8_t* payload{ nullptr }; - size_t payloadLen{ 0u }; - }; -} // namespace PayloadChannel - -#endif diff --git a/worker/include/PayloadChannel/PayloadChannelNotifier.hpp b/worker/include/PayloadChannel/PayloadChannelNotifier.hpp deleted file mode 100644 index c7df84a484..0000000000 --- a/worker/include/PayloadChannel/PayloadChannelNotifier.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef MS_PAYLOAD_CHANNEL_NOTIFIER_HPP -#define MS_PAYLOAD_CHANNEL_NOTIFIER_HPP - -#include "common.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" -#include -#include - -using json = nlohmann::json; - -namespace PayloadChannel -{ - class PayloadChannelNotifier - { - public: - explicit PayloadChannelNotifier(PayloadChannel::PayloadChannelSocket* payloadChannel); - - public: - void Emit(const std::string& targetId, const char* event, const uint8_t* payload, size_t payloadLen); - void Emit( - const std::string& targetId, - const char* event, - json& data, - const uint8_t* payload, - size_t payloadLen); - void Emit( - const std::string& targetId, - const char* event, - const std::string& data, - const uint8_t* payload, - size_t payloadLen); - - private: - // Passed by argument. - PayloadChannel::PayloadChannelSocket* payloadChannel{ nullptr }; - }; -} // namespace PayloadChannel - -#endif diff --git a/worker/include/PayloadChannel/PayloadChannelRequest.hpp b/worker/include/PayloadChannel/PayloadChannelRequest.hpp deleted file mode 100644 index 0ae60fec3b..0000000000 --- a/worker/include/PayloadChannel/PayloadChannelRequest.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef MS_PAYLOAD_CHANNEL_REQUEST_HPP -#define MS_PAYLOAD_CHANNEL_REQUEST_HPP - -#include "common.hpp" -#include -#include -#include - -using json = nlohmann::json; - -namespace PayloadChannel -{ - // Avoid cyclic #include problem by declaring classes instead of including - // the corresponding header files. - class PayloadChannelSocket; - - class PayloadChannelRequest - { - public: - enum class MethodId - { - DATA_CONSUMER_SEND - }; - - public: - static bool IsRequest(const char* msg, size_t msgLen); - - private: - static absl::flat_hash_map string2MethodId; - - public: - PayloadChannelRequest(PayloadChannel::PayloadChannelSocket* channel, char* msg, size_t msgLen); - virtual ~PayloadChannelRequest(); - - public: - void Accept(); - void Accept(json& data); - void Error(const char* reason = nullptr); - void TypeError(const char* reason = nullptr); - void SetPayload(const uint8_t* payload, size_t payloadLen); - - public: - // Passed by argument. - PayloadChannel::PayloadChannelSocket* channel{ nullptr }; - uint32_t id{ 0u }; - std::string method; - MethodId methodId; - std::string handlerId; - std::string data; - const uint8_t* payload{ nullptr }; - size_t payloadLen{ 0u }; - // Others. - bool replied{ false }; - }; -} // namespace PayloadChannel - -#endif diff --git a/worker/include/PayloadChannel/PayloadChannelSocket.hpp b/worker/include/PayloadChannel/PayloadChannelSocket.hpp deleted file mode 100644 index 4191706246..0000000000 --- a/worker/include/PayloadChannel/PayloadChannelSocket.hpp +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef MS_PAYLOAD_CHANNEL_SOCKET_HPP -#define MS_PAYLOAD_CHANNEL_SOCKET_HPP - -#include "common.hpp" -#include "PayloadChannel/PayloadChannelNotification.hpp" -#include "PayloadChannel/PayloadChannelRequest.hpp" -#include "handles/UnixStreamSocket.hpp" -#include -#include - -using json = nlohmann::json; - -namespace PayloadChannel -{ - class ConsumerSocket : public ::UnixStreamSocket - { - public: - class Listener - { - public: - virtual ~Listener() = default; - - public: - virtual void OnConsumerSocketMessage(ConsumerSocket* consumerSocket, char* msg, size_t msgLen) = 0; - virtual void OnConsumerSocketClosed(ConsumerSocket* consumerSocket) = 0; - }; - - public: - ConsumerSocket(int fd, size_t bufferSize, Listener* listener); - ~ConsumerSocket(); - - /* Pure virtual methods inherited from ::UnixStreamSocket. */ - public: - void UserOnUnixStreamRead() override; - void UserOnUnixStreamSocketClosed() override; - - private: - // Passed by argument. - Listener* listener{ nullptr }; - }; - - class ProducerSocket : public ::UnixStreamSocket - { - public: - ProducerSocket(int fd, size_t bufferSize); - - /* Pure virtual methods inherited from ::UnixStreamSocket. */ - public: - void UserOnUnixStreamRead() override - { - } - void UserOnUnixStreamSocketClosed() override - { - } - }; - - class PayloadChannelSocket : public ConsumerSocket::Listener - { - public: - class RequestHandler - { - public: - virtual ~RequestHandler() = default; - - public: - virtual void HandleRequest(PayloadChannel::PayloadChannelRequest* request) = 0; - }; - - class NotificationHandler - { - public: - virtual ~NotificationHandler() = default; - - public: - virtual void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) = 0; - }; - - class Listener : public RequestHandler, public NotificationHandler - { - public: - virtual ~Listener() = default; - - public: - virtual void OnPayloadChannelClosed(PayloadChannel::PayloadChannelSocket* payloadChannel) = 0; - }; - - public: - explicit PayloadChannelSocket(int consumerFd, int producerFd); - explicit PayloadChannelSocket( - PayloadChannelReadFn payloadChannelReadFn, - PayloadChannelReadCtx payloadChannelReadCtx, - PayloadChannelWriteFn payloadChannelWriteFn, - PayloadChannelWriteCtx payloadChannelWriteCtx); - virtual ~PayloadChannelSocket(); - - public: - void Close(); - void SetListener(Listener* listener); - void Send(json& jsonMessage, const uint8_t* payload, size_t payloadLen); - void Send(const std::string& message, const uint8_t* payload, size_t payloadLen); - void Send(json& jsonMessage); - void Send(const std::string& message); - bool CallbackRead(); - - private: - void SendImpl(const uint8_t* message, uint32_t messageLen); - void SendImpl( - const uint8_t* message, uint32_t messageLen, const uint8_t* payload, uint32_t payloadLen); - - /* Pure virtual methods inherited from ConsumerSocket::Listener. */ - public: - void OnConsumerSocketMessage(ConsumerSocket* consumerSocket, char* msg, size_t msgLen) override; - void OnConsumerSocketClosed(ConsumerSocket* consumerSocket) override; - - private: - // Passed by argument. - Listener* listener{ nullptr }; - // Others. - bool closed{ false }; - ConsumerSocket* consumerSocket{ nullptr }; - ProducerSocket* producerSocket{ nullptr }; - PayloadChannelReadFn payloadChannelReadFn{ nullptr }; - PayloadChannelReadCtx payloadChannelReadCtx{ nullptr }; - PayloadChannelWriteFn payloadChannelWriteFn{ nullptr }; - PayloadChannelWriteCtx payloadChannelWriteCtx{ nullptr }; - PayloadChannel::PayloadChannelNotification* ongoingNotification{ nullptr }; - PayloadChannel::PayloadChannelRequest* ongoingRequest{ nullptr }; - uv_async_t* uvReadHandle{ nullptr }; - uint8_t* writeBuffer{ nullptr }; - }; -} // namespace PayloadChannel - -#endif diff --git a/worker/include/RTC/ActiveSpeakerObserver.hpp b/worker/include/RTC/ActiveSpeakerObserver.hpp index cf4be62223..586820fdae 100644 --- a/worker/include/RTC/ActiveSpeakerObserver.hpp +++ b/worker/include/RTC/ActiveSpeakerObserver.hpp @@ -5,7 +5,6 @@ #include "RTC/Shared.hpp" #include "handles/Timer.hpp" #include -#include #include #include @@ -71,7 +70,10 @@ namespace RTC public: ActiveSpeakerObserver( - RTC::Shared* shared, const std::string& id, RTC::RtpObserver::Listener* listener, json& data); + RTC::Shared* shared, + const std::string& id, + RTC::RtpObserver::Listener* listener, + const FBS::ActiveSpeakerObserver::ActiveSpeakerObserverOptions* options); ~ActiveSpeakerObserver() override; public: diff --git a/worker/include/RTC/AudioLevelObserver.hpp b/worker/include/RTC/AudioLevelObserver.hpp index c0007e7301..54cec18f0f 100644 --- a/worker/include/RTC/AudioLevelObserver.hpp +++ b/worker/include/RTC/AudioLevelObserver.hpp @@ -5,9 +5,6 @@ #include "RTC/Shared.hpp" #include "handles/Timer.hpp" #include -#include - -using json = nlohmann::json; namespace RTC { @@ -22,7 +19,10 @@ namespace RTC public: AudioLevelObserver( - RTC::Shared* shared, const std::string& id, RTC::RtpObserver::Listener* listener, json& data); + RTC::Shared* shared, + const std::string& id, + RTC::RtpObserver::Listener* listener, + const FBS::AudioLevelObserver::AudioLevelObserverOptions* options); ~AudioLevelObserver() override; public: diff --git a/worker/include/RTC/Consumer.hpp b/worker/include/RTC/Consumer.hpp index 016a5ed085..5802777632 100644 --- a/worker/include/RTC/Consumer.hpp +++ b/worker/include/RTC/Consumer.hpp @@ -4,6 +4,7 @@ #include "common.hpp" #include "Channel/ChannelRequest.hpp" #include "Channel/ChannelSocket.hpp" +#include "FBS/consumer_generated.h" #include "RTC/RTCP/CompoundPacket.hpp" #include "RTC/RTCP/FeedbackPs.hpp" #include "RTC/RTCP/FeedbackPsFir.hpp" @@ -17,12 +18,9 @@ #include "RTC/RtpStreamSend.hpp" #include "RTC/Shared.hpp" #include -#include #include #include -using json = nlohmann::json; - namespace RTC { class Consumer : public Channel::ChannelSocket::RequestHandler @@ -65,14 +63,20 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data, + const FBS::Transport::ConsumeRequest* data, RTC::RtpParameters::Type type); virtual ~Consumer(); public: - virtual void FillJson(json& jsonObject) const; - virtual void FillJsonStats(json& jsonArray) const = 0; - virtual void FillJsonScore(json& jsonObject) const = 0; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + virtual flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) = 0; + virtual flatbuffers::Offset FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const + { + return 0; + }; RTC::Media::Kind GetKind() const { return this->kind; @@ -166,6 +170,7 @@ namespace RTC void EmitTraceEventPliType(uint32_t ssrc) const; void EmitTraceEventFirType(uint32_t ssrc) const; void EmitTraceEventNackType() const; + void EmitTraceEvent(flatbuffers::Offset& notification) const; private: virtual void UserOnTransportConnected() = 0; diff --git a/worker/include/RTC/DataConsumer.hpp b/worker/include/RTC/DataConsumer.hpp index 46d1f15629..d888e3c3c9 100644 --- a/worker/include/RTC/DataConsumer.hpp +++ b/worker/include/RTC/DataConsumer.hpp @@ -4,11 +4,8 @@ #include "common.hpp" #include "Channel/ChannelRequest.hpp" #include "Channel/ChannelSocket.hpp" -#include "PayloadChannel/PayloadChannelRequest.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" #include "RTC/SctpDictionaries.hpp" #include "RTC/Shared.hpp" -#include #include namespace RTC @@ -17,8 +14,7 @@ namespace RTC // (this is to avoid circular dependencies). class SctpAssociation; - class DataConsumer : public Channel::ChannelSocket::RequestHandler, - public PayloadChannel::PayloadChannelSocket::RequestHandler + class DataConsumer : public Channel::ChannelSocket::RequestHandler { protected: using onQueuedCallback = const std::function; @@ -53,13 +49,15 @@ namespace RTC const std::string& dataProducerId, RTC::SctpAssociation* sctpAssociation, RTC::DataConsumer::Listener* listener, - json& data, + const FBS::Transport::ConsumeDataRequest* data, size_t maxMessageSize); virtual ~DataConsumer(); public: - void FillJson(json& jsonObject) const; - void FillJsonStats(json& jsonArray) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) const; Type GetType() const { return this->type; @@ -91,10 +89,6 @@ namespace RTC public: void HandleRequest(Channel::ChannelRequest* request) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::RequestHandler. */ - public: - void HandleRequest(PayloadChannel::PayloadChannelRequest* request) override; - public: // Passed by argument. const std::string id; diff --git a/worker/include/RTC/DataProducer.hpp b/worker/include/RTC/DataProducer.hpp index 952cc0df9f..6ebe066ba1 100644 --- a/worker/include/RTC/DataProducer.hpp +++ b/worker/include/RTC/DataProducer.hpp @@ -4,17 +4,15 @@ #include "common.hpp" #include "Channel/ChannelRequest.hpp" #include "Channel/ChannelSocket.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" #include "RTC/RTCP/Packet.hpp" #include "RTC/SctpDictionaries.hpp" #include "RTC/Shared.hpp" -#include #include namespace RTC { class DataProducer : public Channel::ChannelSocket::RequestHandler, - public PayloadChannel::PayloadChannelSocket::NotificationHandler + public Channel::ChannelSocket::NotificationHandler { public: class Listener @@ -41,12 +39,14 @@ namespace RTC const std::string& id, size_t maxMessageSize, RTC::DataProducer::Listener* listener, - json& data); + const FBS::Transport::ProduceDataRequest* data); virtual ~DataProducer(); public: - void FillJson(json& jsonObject) const; - void FillJsonStats(json& jsonArray) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) const; Type GetType() const { return this->type; @@ -61,9 +61,9 @@ namespace RTC public: void HandleRequest(Channel::ChannelRequest* request) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ + /* Methods inherited from Channel::ChannelSocket::NotificationHandler. */ public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; + void HandleNotification(Channel::ChannelNotification* notification) override; public: // Passed by argument. diff --git a/worker/include/RTC/DirectTransport.hpp b/worker/include/RTC/DirectTransport.hpp index 046ac8d0ce..9b687c6086 100644 --- a/worker/include/RTC/DirectTransport.hpp +++ b/worker/include/RTC/DirectTransport.hpp @@ -10,12 +10,17 @@ namespace RTC { public: DirectTransport( - RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data); + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::DirectTransport::DirectTransportOptions* options); ~DirectTransport() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) override; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder); + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; private: bool IsConnected() const override; @@ -39,9 +44,9 @@ namespace RTC public: void HandleRequest(Channel::ChannelRequest* request) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ + /* Methods inherited from Channel::ChannelSocket::NotificationHandler. */ public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; + void HandleNotification(Channel::ChannelNotification* notification) override; }; } // namespace RTC diff --git a/worker/include/RTC/IceCandidate.hpp b/worker/include/RTC/IceCandidate.hpp index 7b684365a0..448dc390b9 100644 --- a/worker/include/RTC/IceCandidate.hpp +++ b/worker/include/RTC/IceCandidate.hpp @@ -2,13 +2,12 @@ #define MS_RTC_ICE_CANDIDATE_HPP #include "common.hpp" +#include "FBS/webRtcTransport_generated.h" #include "RTC/TcpServer.hpp" #include "RTC/UdpSocket.hpp" -#include +#include #include -using json = nlohmann::json; - namespace RTC { class IceCandidate @@ -59,7 +58,8 @@ namespace RTC { } - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; private: // Others. diff --git a/worker/include/RTC/Parameters.hpp b/worker/include/RTC/Parameters.hpp index eb7cd8f188..c0ac24b049 100644 --- a/worker/include/RTC/Parameters.hpp +++ b/worker/include/RTC/Parameters.hpp @@ -2,13 +2,11 @@ #define MS_RTC_PARAMETERS_HPP #include "common.hpp" +#include "FBS/rtpParameters_generated.h" #include -#include #include #include -using json = nlohmann::json; - namespace RTC { class Parameters @@ -62,8 +60,9 @@ namespace RTC }; public: - void FillJson(json& jsonObject) const; - void Set(json& data); + std::vector> FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + void Set(const flatbuffers::Vector>* data); bool HasBoolean(const std::string& key) const; bool HasInteger(const std::string& key) const; bool HasPositiveInteger(const std::string& key) const; diff --git a/worker/include/RTC/PipeConsumer.hpp b/worker/include/RTC/PipeConsumer.hpp index 3de9030ee4..6d998124a5 100644 --- a/worker/include/RTC/PipeConsumer.hpp +++ b/worker/include/RTC/PipeConsumer.hpp @@ -16,13 +16,16 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data); + const FBS::Transport::ConsumeRequest* data); ~PipeConsumer() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) const override; - void FillJsonScore(json& jsonObject) const override; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) override; + flatbuffers::Offset FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const override; void ProducerRtpStream(RTC::RtpStream* rtpStream, uint32_t mappedSsrc) override; void ProducerNewRtpStream(RTC::RtpStream* rtpStream, uint32_t mappedSsrc) override; void ProducerRtpStreamScore(RTC::RtpStream* rtpStream, uint8_t score, uint8_t previousScore) override; diff --git a/worker/include/RTC/PipeTransport.hpp b/worker/include/RTC/PipeTransport.hpp index 2f0b9c39eb..f8560f714f 100644 --- a/worker/include/RTC/PipeTransport.hpp +++ b/worker/include/RTC/PipeTransport.hpp @@ -1,6 +1,7 @@ #ifndef MS_RTC_PIPE_TRANSPORT_HPP #define MS_RTC_PIPE_TRANSPORT_HPP +#include "FBS/pipeTransport_generated.h" #include "RTC/Shared.hpp" #include "RTC/SrtpSession.hpp" #include "RTC/Transport.hpp" @@ -25,20 +26,25 @@ namespace RTC public: PipeTransport( - RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data); + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::PipeTransport::PipeTransportOptions* options); ~PipeTransport() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) override; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder); + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ public: void HandleRequest(Channel::ChannelRequest* request) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ + /* Methods inherited from Channel::ChannelSocket::NotificationHandler. */ public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; + void HandleNotification(Channel::ChannelNotification* notification) override; private: bool IsConnected() const override; diff --git a/worker/include/RTC/PlainTransport.hpp b/worker/include/RTC/PlainTransport.hpp index 2df62205d1..f16efdea68 100644 --- a/worker/include/RTC/PlainTransport.hpp +++ b/worker/include/RTC/PlainTransport.hpp @@ -1,6 +1,7 @@ #ifndef MS_RTC_PLAIN_TRANSPORT_HPP #define MS_RTC_PLAIN_TRANSPORT_HPP +#include "FBS/plainTransport_generated.h" #include "RTC/Shared.hpp" #include "RTC/SrtpSession.hpp" #include "RTC/Transport.hpp" @@ -25,20 +26,22 @@ namespace RTC public: PlainTransport( - RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data); + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::PlainTransport::PlainTransportOptions* options); ~PlainTransport() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) override; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder); + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ public: void HandleRequest(Channel::ChannelRequest* request) override; - - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ - public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; + void HandleNotification(Channel::ChannelNotification* notification) override; private: bool IsConnected() const override; @@ -63,6 +66,8 @@ namespace RTC void OnRtpDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); void OnRtcpDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); void OnSctpDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); + void EmitTuple() const; + void EmitRtcpTuple() const; /* Pure virtual methods inherited from RTC::UdpSocket::Listener. */ public: diff --git a/worker/include/RTC/PortManager.hpp b/worker/include/RTC/PortManager.hpp index ca925ef46f..4300548385 100644 --- a/worker/include/RTC/PortManager.hpp +++ b/worker/include/RTC/PortManager.hpp @@ -5,7 +5,6 @@ #include "Settings.hpp" #include #include -#include #include #include @@ -45,7 +44,6 @@ namespace RTC { return Unbind(Transport::TCP, ip, port); } - static void FillJson(json& jsonObject); private: static uv_handle_t* Bind(Transport transport, std::string& ip); diff --git a/worker/include/RTC/Producer.hpp b/worker/include/RTC/Producer.hpp index 9fb4306586..228f97e433 100644 --- a/worker/include/RTC/Producer.hpp +++ b/worker/include/RTC/Producer.hpp @@ -4,7 +4,6 @@ #include "common.hpp" #include "Channel/ChannelRequest.hpp" #include "Channel/ChannelSocket.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" #include "RTC/KeyFrameRequestManager.hpp" #include "RTC/RTCP/CompoundPacket.hpp" #include "RTC/RTCP/Packet.hpp" @@ -15,18 +14,15 @@ #include "RTC/RtpPacket.hpp" #include "RTC/RtpStreamRecv.hpp" #include "RTC/Shared.hpp" -#include #include #include -using json = nlohmann::json; - namespace RTC { class Producer : public RTC::RtpStreamRecv::Listener, public RTC::KeyFrameRequestManager::Listener, public Channel::ChannelSocket::RequestHandler, - public PayloadChannel::PayloadChannelSocket::NotificationHandler + public Channel::ChannelSocket::NotificationHandler { public: class Listener @@ -93,12 +89,18 @@ namespace RTC }; public: - Producer(RTC::Shared* shared, const std::string& id, RTC::Producer::Listener* listener, json& data); + Producer( + RTC::Shared* shared, + const std::string& id, + RTC::Producer::Listener* listener, + const FBS::Transport::ProduceRequest* data); virtual ~Producer(); public: - void FillJson(json& jsonObject) const; - void FillJsonStats(json& jsonArray) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder); RTC::Media::Kind GetKind() const { return this->kind; @@ -137,9 +139,9 @@ namespace RTC public: void HandleRequest(Channel::ChannelRequest* request) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ + /* Methods inherited from Channel::ChannelSocket::NotificationHandler. */ public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; + void HandleNotification(Channel::ChannelNotification* notification) override; private: RTC::RtpStreamRecv* GetRtpStream(RTC::RtpPacket* packet); @@ -155,6 +157,7 @@ namespace RTC void EmitTraceEventPliType(uint32_t ssrc) const; void EmitTraceEventFirType(uint32_t ssrc) const; void EmitTraceEventNackType() const; + void EmitTraceEvent(flatbuffers::Offset& notification) const; /* Pure virtual methods inherited from RTC::RtpStreamRecv::Listener. */ public: diff --git a/worker/include/RTC/Router.hpp b/worker/include/RTC/Router.hpp index 6aa38d072c..1715b2a0b0 100644 --- a/worker/include/RTC/Router.hpp +++ b/worker/include/RTC/Router.hpp @@ -2,9 +2,8 @@ #define MS_RTC_ROUTER_HPP #include "common.hpp" +#include "Channel/ChannelNotification.hpp" #include "Channel/ChannelRequest.hpp" -#include "PayloadChannel/PayloadChannelNotification.hpp" -#include "PayloadChannel/PayloadChannelRequest.hpp" #include "RTC/Consumer.hpp" #include "RTC/DataConsumer.hpp" #include "RTC/DataProducer.hpp" @@ -16,12 +15,9 @@ #include "RTC/Transport.hpp" #include "RTC/WebRtcServer.hpp" #include -#include #include #include -using json = nlohmann::json; - namespace RTC { class Router : public RTC::Transport::Listener, @@ -44,17 +40,18 @@ namespace RTC virtual ~Router(); public: - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ public: void HandleRequest(Channel::ChannelRequest* request) override; private: - void SetNewTransportIdFromData(json& data, std::string& transportId) const; - RTC::Transport* GetTransportFromData(json& data) const; - void SetNewRtpObserverIdFromData(json& data, std::string& rtpObserverId) const; - RTC::RtpObserver* GetRtpObserverFromData(json& data) const; + RTC::Transport* GetTransportById(const std::string& transportId) const; + RTC::RtpObserver* GetRtpObserverById(const std::string& rtpObserverId) const; + void CheckNoTransport(const std::string& transportId) const; + void CheckNoRtpObserver(const std::string& rtpObserverId) const; /* Pure virtual methods inherited from RTC::Transport::Listener. */ public: @@ -83,7 +80,7 @@ namespace RTC uint32_t mappedSsrc, uint8_t& worstRemoteFractionLost) override; void OnTransportNewConsumer( - RTC::Transport* transport, RTC::Consumer* consumer, std::string& producerId) override; + RTC::Transport* transport, RTC::Consumer* consumer, const std::string& producerId) override; void OnTransportConsumerClosed(RTC::Transport* transport, RTC::Consumer* consumer) override; void OnTransportConsumerProducerClosed(RTC::Transport* transport, RTC::Consumer* consumer) override; void OnTransportConsumerKeyFrameRequested( diff --git a/worker/include/RTC/RtpDictionaries.hpp b/worker/include/RTC/RtpDictionaries.hpp index 7cf12f2afa..735db78a08 100644 --- a/worker/include/RTC/RtpDictionaries.hpp +++ b/worker/include/RTC/RtpDictionaries.hpp @@ -2,14 +2,12 @@ #define MS_RTC_RTP_DICTIONARIES_HPP #include "common.hpp" +#include "FBS/rtpParameters_generated.h" #include "RTC/Parameters.hpp" #include -#include #include #include -using json = nlohmann::json; - namespace RTC { class Media @@ -155,9 +153,10 @@ namespace RTC { public: RtcpFeedback() = default; - explicit RtcpFeedback(json& data); + explicit RtcpFeedback(const FBS::RtpParameters::RtcpFeedback* data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; public: std::string type; @@ -168,9 +167,10 @@ namespace RTC { public: RtpCodecParameters() = default; - explicit RtpCodecParameters(json& data); + explicit RtpCodecParameters(const FBS::RtpParameters::RtpCodecParameters* data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; private: void CheckCodec(); @@ -188,9 +188,9 @@ namespace RTC { public: RtpRtxParameters() = default; - explicit RtpRtxParameters(json& data); + explicit RtpRtxParameters(const FBS::RtpParameters::Rtx* data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; public: uint32_t ssrc{ 0u }; @@ -200,9 +200,10 @@ namespace RTC { public: RtpEncodingParameters() = default; - explicit RtpEncodingParameters(json& data); + explicit RtpEncodingParameters(const FBS::RtpParameters::RtpEncodingParameters* data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; public: uint32_t ssrc{ 0u }; @@ -224,9 +225,11 @@ namespace RTC { public: RtpHeaderExtensionParameters() = default; - explicit RtpHeaderExtensionParameters(json& data); + explicit RtpHeaderExtensionParameters( + const FBS::RtpParameters::RtpHeaderExtensionParameters* const data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; public: std::string uri; @@ -240,13 +243,13 @@ namespace RTC { public: RtcpParameters() = default; - explicit RtcpParameters(json& data); + explicit RtcpParameters(const FBS::RtpParameters::RtcpParameters* data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; public: std::string cname; - uint32_t ssrc{ 0u }; bool reducedSize{ true }; }; @@ -274,9 +277,10 @@ namespace RTC public: RtpParameters() = default; - explicit RtpParameters(json& data); + explicit RtpParameters(const FBS::RtpParameters::RtpParameters* data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; const RTC::RtpCodecParameters* GetCodecForEncoding(RtpEncodingParameters& encoding) const; const RTC::RtpCodecParameters* GetRtxCodecForEncoding(RtpEncodingParameters& encoding) const; diff --git a/worker/include/RTC/RtpListener.hpp b/worker/include/RTC/RtpListener.hpp index b6f6d65d37..0591c4ba4f 100644 --- a/worker/include/RTC/RtpListener.hpp +++ b/worker/include/RTC/RtpListener.hpp @@ -4,18 +4,16 @@ #include "common.hpp" #include "RTC/Producer.hpp" #include "RTC/RtpPacket.hpp" -#include #include #include -using json = nlohmann::json; - namespace RTC { class RtpListener { public: - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; void AddProducer(RTC::Producer* producer); void RemoveProducer(RTC::Producer* producer); RTC::Producer* GetProducer(const RTC::RtpPacket* packet); diff --git a/worker/include/RTC/RtpObserver.hpp b/worker/include/RTC/RtpObserver.hpp index 00c8010456..4c78a5f847 100644 --- a/worker/include/RTC/RtpObserver.hpp +++ b/worker/include/RTC/RtpObserver.hpp @@ -50,9 +50,6 @@ namespace RTC virtual void Paused() = 0; virtual void Resumed() = 0; - private: - std::string GetProducerIdFromData(json& data) const; - public: // Passed by argument. const std::string id; diff --git a/worker/include/RTC/RtpPacket.hpp b/worker/include/RTC/RtpPacket.hpp index a585a3babc..f851bab3d5 100644 --- a/worker/include/RTC/RtpPacket.hpp +++ b/worker/include/RTC/RtpPacket.hpp @@ -7,12 +7,9 @@ #include "RTC/RtcLogger.hpp" #include #include -#include #include #include -using json = nlohmann::json; - namespace RTC { // Max MTU size. @@ -148,8 +145,6 @@ namespace RTC void Dump() const; - void FillJson(json& jsonObject) const; - const uint8_t* GetData() const { return (const uint8_t*)this->header; diff --git a/worker/include/RTC/RtpStream.hpp b/worker/include/RTC/RtpStream.hpp index 9a0ca8daa6..9fd3be1b03 100644 --- a/worker/include/RTC/RtpStream.hpp +++ b/worker/include/RTC/RtpStream.hpp @@ -3,6 +3,7 @@ #include "common.hpp" #include "DepLibUV.hpp" +#include "FBS/rtpStream_generated.h" #include "RTC/RTCP/FeedbackPsFir.hpp" #include "RTC/RTCP/FeedbackPsPli.hpp" #include "RTC/RTCP/FeedbackRtpNack.hpp" @@ -15,12 +16,9 @@ #include "RTC/RtpDictionaries.hpp" #include "RTC/RtpPacket.hpp" #include "RTC/RtxStream.hpp" -#include #include #include -using json = nlohmann::json; - namespace RTC { class RtpStream @@ -38,7 +36,8 @@ namespace RTC public: struct Params { - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; size_t encodingIdx{ 0u }; uint32_t ssrc{ 0u }; @@ -62,8 +61,9 @@ namespace RTC RtpStream(RTC::RtpStream::Listener* listener, RTC::RtpStream::Params& params, uint8_t initialScore); virtual ~RtpStream(); - void FillJson(json& jsonObject) const; - virtual void FillJsonStats(json& jsonObject); + flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; + virtual flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder); uint32_t GetEncodingIdx() const { return this->params.encodingIdx; diff --git a/worker/include/RTC/RtpStreamRecv.hpp b/worker/include/RTC/RtpStreamRecv.hpp index afe7c0c83c..a4d538ed59 100644 --- a/worker/include/RTC/RtpStreamRecv.hpp +++ b/worker/include/RTC/RtpStreamRecv.hpp @@ -49,7 +49,8 @@ namespace RTC bool useRtpInactivityCheck); ~RtpStreamRecv(); - void FillJsonStats(json& jsonObject) override; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) override; bool ReceivePacket(RTC::RtpPacket* packet); bool ReceiveRtxPacket(RTC::RtpPacket* packet); RTC::RTCP::ReceiverReport* GetRtcpReceiverReport(); diff --git a/worker/include/RTC/RtpStreamSend.hpp b/worker/include/RTC/RtpStreamSend.hpp index 9c59c897dd..f98d399aca 100644 --- a/worker/include/RTC/RtpStreamSend.hpp +++ b/worker/include/RTC/RtpStreamSend.hpp @@ -28,7 +28,8 @@ namespace RTC RTC::RtpStreamSend::Listener* listener, RTC::RtpStream::Params& params, std::string& mid); ~RtpStreamSend() override; - void FillJsonStats(json& jsonObject) override; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) override; void SetRtx(uint8_t payloadType, uint32_t ssrc) override; bool ReceivePacket(RTC::RtpPacket* packet, std::shared_ptr& sharedPacket); void ReceiveNack(RTC::RTCP::FeedbackRtpNackPacket* nackPacket); diff --git a/worker/include/RTC/RtxStream.hpp b/worker/include/RTC/RtxStream.hpp index 216c3ba201..c0d862b063 100644 --- a/worker/include/RTC/RtxStream.hpp +++ b/worker/include/RTC/RtxStream.hpp @@ -3,16 +3,14 @@ #include "common.hpp" #include "DepLibUV.hpp" +#include "FBS/rtxStream_generated.h" #include "RTC/RTCP/Packet.hpp" #include "RTC/RTCP/ReceiverReport.hpp" #include "RTC/RTCP/SenderReport.hpp" #include "RTC/RtpDictionaries.hpp" #include "RTC/RtpPacket.hpp" -#include #include -using json = nlohmann::json; - namespace RTC { class RtxStream @@ -20,7 +18,8 @@ namespace RTC public: struct Params { - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; uint32_t ssrc{ 0 }; uint8_t payloadType{ 0 }; @@ -34,7 +33,7 @@ namespace RTC explicit RtxStream(RTC::RtxStream::Params& params); virtual ~RtxStream(); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; uint32_t GetSsrc() const { return this->params.ssrc; diff --git a/worker/include/RTC/SctpAssociation.hpp b/worker/include/RTC/SctpAssociation.hpp index 6b6626f04d..0b52a05ebe 100644 --- a/worker/include/RTC/SctpAssociation.hpp +++ b/worker/include/RTC/SctpAssociation.hpp @@ -6,9 +6,6 @@ #include "RTC/DataConsumer.hpp" #include "RTC/DataProducer.hpp" #include -#include - -using json = nlohmann::json; namespace RTC { @@ -81,7 +78,8 @@ namespace RTC ~SctpAssociation(); public: - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; void TransportConnected(); SctpState GetState() const { diff --git a/worker/include/RTC/SctpDictionaries.hpp b/worker/include/RTC/SctpDictionaries.hpp index 9ceebb03a8..162d26b830 100644 --- a/worker/include/RTC/SctpDictionaries.hpp +++ b/worker/include/RTC/SctpDictionaries.hpp @@ -2,10 +2,7 @@ #define MS_RTC_SCTP_DICTIONARIES_HPP #include "common.hpp" -#include -#include - -using json = nlohmann::json; +#include namespace RTC { @@ -13,9 +10,10 @@ namespace RTC { public: SctpStreamParameters() = default; - explicit SctpStreamParameters(json& data); + explicit SctpStreamParameters(const FBS::SctpParameters::SctpStreamParameters* data); - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; public: uint16_t streamId{ 0u }; diff --git a/worker/include/RTC/SctpListener.hpp b/worker/include/RTC/SctpListener.hpp index 4988805e65..504d7d978a 100644 --- a/worker/include/RTC/SctpListener.hpp +++ b/worker/include/RTC/SctpListener.hpp @@ -3,17 +3,15 @@ #include "common.hpp" #include "RTC/DataProducer.hpp" -#include #include -using json = nlohmann::json; - namespace RTC { class SctpListener { public: - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; void AddDataProducer(RTC::DataProducer* dataProducer); void RemoveDataProducer(RTC::DataProducer* dataProducer); RTC::DataProducer* GetDataProducer(uint16_t streamId); diff --git a/worker/include/RTC/Shared.hpp b/worker/include/RTC/Shared.hpp index 90e07f058a..2a71781283 100644 --- a/worker/include/RTC/Shared.hpp +++ b/worker/include/RTC/Shared.hpp @@ -3,7 +3,6 @@ #include "ChannelMessageRegistrator.hpp" #include "Channel/ChannelNotifier.hpp" -#include "PayloadChannel/PayloadChannelNotifier.hpp" namespace RTC { @@ -12,14 +11,12 @@ namespace RTC public: explicit Shared( ChannelMessageRegistrator* channelMessageRegistrator, - Channel::ChannelNotifier* channelNotifier, - PayloadChannel::PayloadChannelNotifier* payloadChannelNotifier); + Channel::ChannelNotifier* channelNotifier); ~Shared(); public: ChannelMessageRegistrator* channelMessageRegistrator{ nullptr }; Channel::ChannelNotifier* channelNotifier{ nullptr }; - PayloadChannel::PayloadChannelNotifier* payloadChannelNotifier{ nullptr }; }; } // namespace RTC diff --git a/worker/include/RTC/SimpleConsumer.hpp b/worker/include/RTC/SimpleConsumer.hpp index 7932d13e2f..c4fa974633 100644 --- a/worker/include/RTC/SimpleConsumer.hpp +++ b/worker/include/RTC/SimpleConsumer.hpp @@ -1,6 +1,7 @@ #ifndef MS_RTC_SIMPLE_CONSUMER_HPP #define MS_RTC_SIMPLE_CONSUMER_HPP +#include "FBS/transport_generated.h" #include "RTC/Consumer.hpp" #include "RTC/RtpStreamSend.hpp" #include "RTC/SeqManager.hpp" @@ -16,13 +17,16 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data); + const FBS::Transport::ConsumeRequest* data); ~SimpleConsumer() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) const override; - void FillJsonScore(json& jsonObject) const override; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) override; + flatbuffers::Offset FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const override; bool IsActive() const override { // clang-format off diff --git a/worker/include/RTC/SimulcastConsumer.hpp b/worker/include/RTC/SimulcastConsumer.hpp index c08dd83af2..f337d418ba 100644 --- a/worker/include/RTC/SimulcastConsumer.hpp +++ b/worker/include/RTC/SimulcastConsumer.hpp @@ -1,6 +1,7 @@ #ifndef MS_RTC_SIMULCAST_CONSUMER_HPP #define MS_RTC_SIMULCAST_CONSUMER_HPP +#include "FBS/consumer_generated.h" #include "RTC/Codecs/PayloadDescriptorHandler.hpp" #include "RTC/Consumer.hpp" #include "RTC/RtpStreamSend.hpp" @@ -17,13 +18,16 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data); + const FBS::Transport::ConsumeRequest* data); ~SimulcastConsumer() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) const override; - void FillJsonScore(json& jsonObject) const override; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) override; + flatbuffers::Offset FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const override; RTC::Consumer::Layers GetPreferredLayers() const override { RTC::Consumer::Layers layers; diff --git a/worker/include/RTC/SvcConsumer.hpp b/worker/include/RTC/SvcConsumer.hpp index 949a86ef65..7a3150428b 100644 --- a/worker/include/RTC/SvcConsumer.hpp +++ b/worker/include/RTC/SvcConsumer.hpp @@ -18,13 +18,16 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data); + const FBS::Transport::ConsumeRequest* data); ~SvcConsumer() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) const override; - void FillJsonScore(json& jsonObject) const override; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) override; + flatbuffers::Offset FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const override; RTC::Consumer::Layers GetPreferredLayers() const override { RTC::Consumer::Layers layers; diff --git a/worker/include/RTC/Transport.hpp b/worker/include/RTC/Transport.hpp index 87e5e81909..0890f2fbde 100644 --- a/worker/include/RTC/Transport.hpp +++ b/worker/include/RTC/Transport.hpp @@ -4,10 +4,10 @@ #include "common.hpp" #include "DepLibUV.hpp" +#include "Channel/ChannelNotification.hpp" #include "Channel/ChannelRequest.hpp" #include "Channel/ChannelSocket.hpp" -#include "PayloadChannel/PayloadChannelNotification.hpp" -#include "PayloadChannel/PayloadChannelRequest.hpp" +#include "FBS/transport_generated.h" #include "RTC/Consumer.hpp" #include "RTC/DataConsumer.hpp" #include "RTC/DataProducer.hpp" @@ -29,11 +29,8 @@ #include "RTC/TransportCongestionControlServer.hpp" #include "handles/Timer.hpp" #include -#include #include -using json = nlohmann::json; - namespace RTC { class Transport : public RTC::Producer::Listener, @@ -44,8 +41,7 @@ namespace RTC public RTC::TransportCongestionControlClient::Listener, public RTC::TransportCongestionControlServer::Listener, public Channel::ChannelSocket::RequestHandler, - public PayloadChannel::PayloadChannelSocket::RequestHandler, - public PayloadChannel::PayloadChannelSocket::NotificationHandler, + public Channel::ChannelSocket::NotificationHandler, #ifdef ENABLE_RTC_SENDER_BANDWIDTH_ESTIMATOR public RTC::SenderBandwidthEstimator::Listener, #endif @@ -87,7 +83,7 @@ namespace RTC uint32_t mappedSsrc, uint8_t& worstRemoteFractionLost) = 0; virtual void OnTransportNewConsumer( - RTC::Transport* transport, RTC::Consumer* consumer, std::string& producerId) = 0; + RTC::Transport* transport, RTC::Consumer* consumer, const std::string& producerId) = 0; virtual void OnTransportConsumerClosed(RTC::Transport* transport, RTC::Consumer* consumer) = 0; virtual void OnTransportConsumerProducerClosed( RTC::Transport* transport, RTC::Consumer* consumer) = 0; @@ -120,27 +116,27 @@ namespace RTC }; public: - Transport(RTC::Shared* shared, const std::string& id, Listener* listener, json& data); + Transport( + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::Transport::Options* options); virtual ~Transport(); public: void CloseProducersAndConsumers(); void ListenServerClosed(); // Subclasses must also invoke the parent Close(). - virtual void FillJson(json& jsonObject) const; - virtual void FillJsonStats(json& jsonArray); + flatbuffers::Offset FillBufferStats(flatbuffers::FlatBufferBuilder& builder); + flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ public: void HandleRequest(Channel::ChannelRequest* request) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::RequestHandler. */ - public: - void HandleRequest(PayloadChannel::PayloadChannelRequest* request) override; - - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ + /* Methods inherited from Channel::ChannelSocket::NotificationHandler. */ public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; + void HandleNotification(Channel::ChannelNotification* notification) override; protected: // Must be called from the subclass. @@ -157,16 +153,12 @@ namespace RTC void ReceiveRtpPacket(RTC::RtpPacket* packet); void ReceiveRtcpPacket(RTC::RTCP::Packet* packet); void ReceiveSctpData(const uint8_t* data, size_t len); - void SetNewProducerIdFromData(json& data, std::string& producerId) const; - RTC::Producer* GetProducerFromData(json& data) const; - void SetNewConsumerIdFromData(json& data, std::string& consumerId) const; - RTC::Consumer* GetConsumerFromData(json& data) const; + RTC::Producer* GetProducerById(const std::string& producerId) const; + RTC::Consumer* GetConsumerById(const std::string& consumerId) const; RTC::Consumer* GetConsumerByMediaSsrc(uint32_t ssrc) const; RTC::Consumer* GetConsumerByRtxSsrc(uint32_t ssrc) const; - void SetNewDataProducerIdFromData(json& data, std::string& dataProducerId) const; - RTC::DataProducer* GetDataProducerFromData(json& data) const; - void SetNewDataConsumerIdFromData(json& data, std::string& dataConsumerId) const; - RTC::DataConsumer* GetDataConsumerFromData(json& data) const; + RTC::DataProducer* GetDataProducerById(const std::string& dataProducerId) const; + RTC::DataConsumer* GetDataConsumerById(const std::string& dataConsumerId) const; private: virtual bool IsConnected() const = 0; @@ -189,6 +181,9 @@ namespace RTC void ComputeOutgoingDesiredBitrate(bool forceBitrate = false); void EmitTraceEventProbationType(RTC::RtpPacket* packet) const; void EmitTraceEventBweType(RTC::TransportCongestionControlClient::Bitrates& bitrates) const; + void CheckNoProducer(const std::string& producerId) const; + void CheckNoDataProducer(const std::string& dataProducerId) const; + void CheckNoDataConsumer(const std::string& dataConsumerId) const; /* Pure virtual methods inherited from RTC::Producer::Listener. */ public: @@ -313,7 +308,7 @@ namespace RTC std::shared_ptr senderBwe{ nullptr }; #endif // Others. - bool direct{ false }; // Whether this Transport allows PayloadChannel comm. + bool direct{ false }; // Whether this Transport allows direct communication. bool destroying{ false }; struct RTC::RtpHeaderExtensionIds recvRtpHeaderExtensionIds; RTC::RtpListener rtpListener; diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 535d221a68..3fc01bca78 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -3,13 +3,12 @@ #include "common.hpp" #include "Utils.hpp" +#include "FBS/transport_generated.h" #include "RTC/TcpConnection.hpp" #include "RTC/UdpSocket.hpp" -#include +#include #include -using json = nlohmann::json; - namespace RTC { class TransportTuple @@ -63,7 +62,7 @@ namespace RTC return this->tcpConnection->IsClosed(); } - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; void Dump() const; diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp index f0197b2d3a..c48dd44830 100644 --- a/worker/include/RTC/WebRtcServer.hpp +++ b/worker/include/RTC/WebRtcServer.hpp @@ -12,7 +12,7 @@ #include "RTC/WebRtcTransport.hpp" #include #include -#include +#include #include #include @@ -24,15 +24,6 @@ namespace RTC public RTC::WebRtcTransport::WebRtcTransportListener, public Channel::ChannelSocket::RequestHandler { - private: - struct ListenInfo - { - RTC::TransportTuple::Protocol protocol; - std::string ip; - std::string announcedIp; - uint16_t port; - }; - private: struct UdpSocketOrTcpServer { @@ -48,11 +39,15 @@ namespace RTC }; public: - WebRtcServer(RTC::Shared* shared, const std::string& id, json& data); + WebRtcServer( + RTC::Shared* shared, + const std::string& id, + const flatbuffers::Vector>* listenInfos); ~WebRtcServer(); public: - void FillJson(json& jsonObject) const; + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; std::vector GetIceCandidates( bool enableUdp, bool enableTcp, bool preferUdp, bool preferTcp); diff --git a/worker/include/RTC/WebRtcTransport.hpp b/worker/include/RTC/WebRtcTransport.hpp index 2eae6d856a..a1d90e3572 100644 --- a/worker/include/RTC/WebRtcTransport.hpp +++ b/worker/include/RTC/WebRtcTransport.hpp @@ -51,19 +51,24 @@ namespace RTC public: WebRtcTransport( - RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data); + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::WebRtcTransport::WebRtcTransportOptions* options); WebRtcTransport( RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, WebRtcTransportListener* webRtcTransportListener, std::vector& iceCandidates, - json& data); + const FBS::WebRtcTransport::WebRtcTransportOptions* options); ~WebRtcTransport() override; public: - void FillJson(json& jsonObject) const override; - void FillJsonStats(json& jsonArray) override; + flatbuffers::Offset FillBufferStats( + flatbuffers::FlatBufferBuilder& builder); + flatbuffers::Offset FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const; void ProcessStunPacketFromWebRtcServer(RTC::TransportTuple* tuple, RTC::StunPacket* packet); void ProcessNonStunPacketFromWebRtcServer( RTC::TransportTuple* tuple, const uint8_t* data, size_t len); @@ -73,9 +78,9 @@ namespace RTC public: void HandleRequest(Channel::ChannelRequest* request) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ + /* Methods inherited from Channel::ChannelSocket::NotificationHandler. */ public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; + void HandleNotification(Channel::ChannelNotification* notification) override; private: bool IsConnected() const override; diff --git a/worker/include/Utils.hpp b/worker/include/Utils.hpp index d41ecb6551..8965f9812f 100644 --- a/worker/include/Utils.hpp +++ b/worker/include/Utils.hpp @@ -5,7 +5,6 @@ #include #include #include // std::memcmp(), std::memcpy() -#include #include #include #ifdef _WIN32 @@ -15,8 +14,6 @@ #define __builtin_popcount __popcnt #endif -using json = nlohmann::json; - namespace Utils { class IP @@ -291,8 +288,6 @@ namespace Utils static uint8_t* Base64Decode(const uint8_t* data, size_t len, size_t& outLen); static uint8_t* Base64Decode(const std::string& str, size_t& outLen); - - static std::vector Split(const std::string& str, char separator, size_t limit = 0); }; class Time @@ -355,26 +350,6 @@ namespace Utils return static_cast(((ms << 18) + 500) / 1000) & 0x00FFFFFF; } }; - - class Json - { - public: - static bool IsPositiveInteger(const json& value) - { - if (value.is_number_unsigned()) - { - return true; - } - else if (value.is_number_integer()) - { - return value.get() >= 0; - } - else - { - return false; - } - } - }; } // namespace Utils #endif diff --git a/worker/include/Worker.hpp b/worker/include/Worker.hpp index 48d993bf7a..76579fcfed 100644 --- a/worker/include/Worker.hpp +++ b/worker/include/Worker.hpp @@ -4,57 +4,43 @@ #include "common.hpp" #include "Channel/ChannelRequest.hpp" #include "Channel/ChannelSocket.hpp" -#include "PayloadChannel/PayloadChannelNotification.hpp" -#include "PayloadChannel/PayloadChannelRequest.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" +#include "FBS/worker_generated.h" #include "RTC/Router.hpp" #include "RTC/Shared.hpp" #include "RTC/WebRtcServer.hpp" #include "handles/SignalsHandler.hpp" #include -#include +#include #include -using json = nlohmann::json; - class Worker : public Channel::ChannelSocket::Listener, - public PayloadChannel::PayloadChannelSocket::Listener, public SignalsHandler::Listener, public RTC::Router::Listener { public: - explicit Worker(Channel::ChannelSocket* channel, PayloadChannel::PayloadChannelSocket* payloadChannel); + explicit Worker(Channel::ChannelSocket* channel); ~Worker(); private: void Close(); - void FillJson(json& jsonObject) const; - void FillJsonResourceUsage(json& jsonObject) const; - void SetNewWebRtcServerIdFromData(json& data, std::string& webRtcServerId) const; - RTC::WebRtcServer* GetWebRtcServerFromData(json& data) const; - void SetNewRouterIdFromData(json& data, std::string& routerId) const; - RTC::Router* GetRouterFromData(json& data) const; + flatbuffers::Offset FillBuffer(flatbuffers::FlatBufferBuilder& builder) const; + flatbuffers::Offset FillBufferResourceUsage( + flatbuffers::FlatBufferBuilder& builder) const; + void SetNewRouterId(std::string& routerId) const; + RTC::WebRtcServer* GetWebRtcServer(const std::string& webRtcServerId) const; + RTC::Router* GetRouter(const std::string& routerId) const; + void CheckNoWebRtcServer(const std::string& webRtcServerId) const; + void CheckNoRouter(const std::string& webRtcServerId) const; /* Methods inherited from Channel::ChannelSocket::RequestHandler. */ public: void HandleRequest(Channel::ChannelRequest* request) override; + void HandleNotification(Channel::ChannelNotification* notification) override; /* Methods inherited from Channel::ChannelSocket::Listener. */ public: void OnChannelClosed(Channel::ChannelSocket* channel) override; - /* Methods inherited from PayloadChannel::PayloadChannelSocket::RequestHandler. */ -public: - void HandleRequest(PayloadChannel::PayloadChannelRequest* request) override; - - /* Methods inherited from PayloadChannel::PayloadChannelSocket::NotificationHandler. */ -public: - void HandleNotification(PayloadChannel::PayloadChannelNotification* notification) override; - - /* Methods inherited from PayloadChannel::PayloadChannelSocket::Listener. */ -public: - void OnPayloadChannelClosed(PayloadChannel::PayloadChannelSocket* payloadChannel) override; - /* Methods inherited from SignalsHandler::Listener. */ public: void OnSignal(SignalsHandler* signalsHandler, int signum) override; @@ -66,7 +52,6 @@ class Worker : public Channel::ChannelSocket::Listener, private: // Passed by argument. Channel::ChannelSocket* channel{ nullptr }; - PayloadChannel::PayloadChannelSocket* payloadChannel{ nullptr }; // Allocated by this. SignalsHandler* signalsHandler{ nullptr }; RTC::Shared* shared{ nullptr }; diff --git a/worker/include/common.hpp b/worker/include/common.hpp index f019dd411c..5b1ba0dedd 100644 --- a/worker/include/common.hpp +++ b/worker/include/common.hpp @@ -41,28 +41,4 @@ using ChannelWriteCtx = void*; using ChannelWriteFn = void (*)(const uint8_t* /* message */, uint32_t /* messageLen */, ChannelWriteCtx /* ctx */); -using PayloadChannelReadCtx = void*; -using PayloadChannelReadFreeFn = void (*)(uint8_t*, uint32_t, size_t); -// Returns `PayloadChannelReadFree` on successful read that must be used to free -// `message` and `payload`. -using PayloadChannelReadFn = PayloadChannelReadFreeFn (*)( - uint8_t** /* message */, - uint32_t* /* messageLen */, - size_t* /* messageCtx */, - uint8_t** /* payload */, - uint32_t* /* payloadLen */, - size_t* /* payloadCapacity */, - // This is `uv_async_t` handle that can be called later with `uv_async_send()` - // when there is more data to read. - const void* /* handle */, - PayloadChannelReadCtx /* ctx */); - -using PayloadChannelWriteCtx = void*; -using PayloadChannelWriteFn = void (*)( - const uint8_t* /* message */, - uint32_t /* messageLen */, - const uint8_t* /* payload */, - uint32_t /* payloadLen */, - ChannelWriteCtx /* ctx */); - #endif diff --git a/worker/include/lib.hpp b/worker/include/lib.hpp index 36d86d2d74..513e354b7d 100644 --- a/worker/include/lib.hpp +++ b/worker/include/lib.hpp @@ -11,8 +11,4 @@ extern "C" int mediasoup_worker_run( ChannelReadFn channelReadFn, ChannelReadCtx channelReadCtx, ChannelWriteFn channelWriteFn, - ChannelWriteCtx channelWriteCtx, - PayloadChannelReadFn payloadChannelReadFn, - PayloadChannelReadCtx payloadChannelReadCtx, - PayloadChannelWriteFn payloadChannelWriteFn, - PayloadChannelWriteCtx payloadChannelWriteCtx); + ChannelWriteCtx channelWriteCtx); diff --git a/worker/meson.build b/worker/meson.build index 4be31c0c0b..b14f373bdb 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -68,11 +68,8 @@ common_sources = [ 'src/handles/UnixStreamSocket.cpp', 'src/Channel/ChannelNotifier.cpp', 'src/Channel/ChannelRequest.cpp', + 'src/Channel/ChannelNotification.cpp', 'src/Channel/ChannelSocket.cpp', - 'src/PayloadChannel/PayloadChannelNotification.cpp', - 'src/PayloadChannel/PayloadChannelNotifier.cpp', - 'src/PayloadChannel/PayloadChannelRequest.cpp', - 'src/PayloadChannel/PayloadChannelSocket.cpp', 'src/RTC/ActiveSpeakerObserver.cpp', 'src/RTC/AudioLevelObserver.cpp', 'src/RTC/Consumer.cpp', @@ -175,12 +172,6 @@ openssl_proj = subproject( 'warning_level=0', ], ) -nlohmann_json_proj = subproject( - 'nlohmann_json', - default_options: [ - 'warning_level=0', - ], -) libuv_proj = subproject( 'libuv', default_options: [ @@ -217,16 +208,22 @@ catch2_proj = subproject( 'warning_level=0', ], ) +flatbuffers_proj = subproject( + 'flatbuffers', + default_options: [ + 'warning_level=0', + ], +) libwebrtc_include_directories = include_directories('include') subdir('deps/libwebrtc') dependencies = [ abseil_cpp_proj.get_variable('absl_container_dep'), openssl_proj.get_variable('openssl_dep'), - nlohmann_json_proj.get_variable('nlohmann_json_dep'), libuv_proj.get_variable('libuv_dep'), libsrtp2_proj.get_variable('libsrtp2_dep'), usrsctp_proj.get_variable('usrsctp_dep'), + flatbuffers_proj.get_variable('flatbuffers_dep'), libwebrtc_dep, ] @@ -237,6 +234,7 @@ link_whole = [ libuv_proj.get_variable('libuv'), libsrtp2_proj.get_variable('libsrtp2'), usrsctp_proj.get_variable('usrsctp'), + flatbuffers_proj.get_variable('flatbuffers_lib'), libwebrtc, ] @@ -290,8 +288,6 @@ mediasoup_worker_test = executable( ], sources: common_sources + [ 'test/src/tests.cpp', - 'test/src/PayloadChannel/TestPayloadChannelNotification.cpp', - 'test/src/PayloadChannel/TestPayloadChannelRequest.cpp', 'test/src/RTC/TestKeyFrameRequestManager.cpp', 'test/src/RTC/TestNackGenerator.cpp', 'test/src/RTC/TestRateCalculator.cpp', @@ -330,7 +326,6 @@ mediasoup_worker_test = executable( 'test/src/RTC/RTCP/TestXr.cpp', 'test/src/Utils/TestBits.cpp', 'test/src/Utils/TestIP.cpp', - 'test/src/Utils/TestJson.cpp', 'test/src/Utils/TestString.cpp', 'test/src/Utils/TestTime.cpp', ], diff --git a/worker/src/Channel/ChannelNotification.cpp b/worker/src/Channel/ChannelNotification.cpp new file mode 100644 index 0000000000..fd2b1809de --- /dev/null +++ b/worker/src/Channel/ChannelNotification.cpp @@ -0,0 +1,41 @@ +#define MS_CLASS "Channel::ChannelNotification" +// #define MS_LOG_DEV_LEVEL 3 + +#include "Channel/ChannelNotification.hpp" +#include "Logger.hpp" +#include "MediaSoupErrors.hpp" + +namespace Channel +{ + /* Class variables. */ + + // clang-format off + absl::flat_hash_map ChannelNotification::event2String = + { + { FBS::Notification::Event::TRANSPORT_SEND_RTCP, "transport.sendRtcp" }, + { FBS::Notification::Event::PRODUCER_SEND, "producer.send" }, + { FBS::Notification::Event::DATA_PRODUCER_SEND, "dataProducer.send" }, + }; + // clang-format on + + /* Instance methods. */ + + ChannelNotification::ChannelNotification(const FBS::Notification::Notification* notification) + { + MS_TRACE(); + + this->data = notification; + this->event = notification->event(); + + auto eventCStrIt = ChannelNotification::event2String.find(this->event); + + if (eventCStrIt == ChannelNotification::event2String.end()) + MS_THROW_ERROR("unknown event '%" PRIu8 "'", this->event); + + this->eventCStr = eventCStrIt->second; + + // Handler ID is optional. + if (flatbuffers::IsFieldPresent(this->data, FBS::Notification::Notification::VT_HANDLERID)) + this->handlerId = this->data->handlerId()->str(); + } +} // namespace Channel diff --git a/worker/src/Channel/ChannelNotifier.cpp b/worker/src/Channel/ChannelNotifier.cpp index 8ef6b23b2a..78a354940b 100644 --- a/worker/src/Channel/ChannelNotifier.cpp +++ b/worker/src/Channel/ChannelNotifier.cpp @@ -10,57 +10,4 @@ namespace Channel { MS_TRACE(); } - - void ChannelNotifier::Emit(uint64_t targetId, const char* event) - { - MS_TRACE(); - - json jsonNotification = json::object(); - - jsonNotification["targetId"] = targetId; - jsonNotification["event"] = event; - - this->channel->Send(jsonNotification); - } - - void ChannelNotifier::Emit(const std::string& targetId, const char* event) - { - MS_TRACE(); - - json jsonNotification = json::object(); - - jsonNotification["targetId"] = targetId; - jsonNotification["event"] = event; - - this->channel->Send(jsonNotification); - } - - void ChannelNotifier::Emit(const std::string& targetId, const char* event, json& data) - { - MS_TRACE(); - - json jsonNotification = json::object(); - - jsonNotification["targetId"] = targetId; - jsonNotification["event"] = event; - jsonNotification["data"] = data; - - this->channel->Send(jsonNotification); - } - - void ChannelNotifier::Emit(const std::string& targetId, const char* event, const std::string& data) - { - MS_TRACE(); - - std::string notification("{\"targetId\":\""); - - notification.append(targetId); - notification.append("\",\"event\":\""); - notification.append(event); - notification.append("\",\"data\":"); - notification.append(data); - notification.append("}"); - - this->channel->Send(notification); - } } // namespace Channel diff --git a/worker/src/Channel/ChannelRequest.cpp b/worker/src/Channel/ChannelRequest.cpp index d107b39329..6b19ffffba 100644 --- a/worker/src/Channel/ChannelRequest.cpp +++ b/worker/src/Channel/ChannelRequest.cpp @@ -4,140 +4,107 @@ #include "Channel/ChannelRequest.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include "Utils.hpp" namespace Channel { /* Class variables. */ // clang-format off - absl::flat_hash_map ChannelRequest::string2MethodId = + absl::flat_hash_map ChannelRequest::method2String = { - { "worker.close", ChannelRequest::MethodId::WORKER_CLOSE }, - { "worker.dump", ChannelRequest::MethodId::WORKER_DUMP }, - { "worker.getResourceUsage", ChannelRequest::MethodId::WORKER_GET_RESOURCE_USAGE }, - { "worker.updateSettings", ChannelRequest::MethodId::WORKER_UPDATE_SETTINGS }, - { "worker.createWebRtcServer", ChannelRequest::MethodId::WORKER_CREATE_WEBRTC_SERVER }, - { "worker.createRouter", ChannelRequest::MethodId::WORKER_CREATE_ROUTER }, - { "worker.closeWebRtcServer", ChannelRequest::MethodId::WORKER_WEBRTC_SERVER_CLOSE }, - { "webRtcServer.dump", ChannelRequest::MethodId::WEBRTC_SERVER_DUMP }, - { "worker.closeRouter", ChannelRequest::MethodId::WORKER_CLOSE_ROUTER }, - { "router.dump", ChannelRequest::MethodId::ROUTER_DUMP }, - { "router.createWebRtcTransport", ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT }, - { "router.createWebRtcTransportWithServer", ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT_WITH_SERVER }, - { "router.createPlainTransport", ChannelRequest::MethodId::ROUTER_CREATE_PLAIN_TRANSPORT }, - { "router.createPipeTransport", ChannelRequest::MethodId::ROUTER_CREATE_PIPE_TRANSPORT }, - { "router.createDirectTransport", ChannelRequest::MethodId::ROUTER_CREATE_DIRECT_TRANSPORT }, - { "router.closeTransport", ChannelRequest::MethodId::ROUTER_CLOSE_TRANSPORT }, - { "router.createActiveSpeakerObserver", ChannelRequest::MethodId::ROUTER_CREATE_ACTIVE_SPEAKER_OBSERVER }, - { "router.createAudioLevelObserver", ChannelRequest::MethodId::ROUTER_CREATE_AUDIO_LEVEL_OBSERVER }, - { "router.closeRtpObserver", ChannelRequest::MethodId::ROUTER_CLOSE_RTP_OBSERVER }, - { "transport.dump", ChannelRequest::MethodId::TRANSPORT_DUMP }, - { "transport.getStats", ChannelRequest::MethodId::TRANSPORT_GET_STATS }, - { "transport.connect", ChannelRequest::MethodId::TRANSPORT_CONNECT }, - { "transport.setMaxIncomingBitrate", ChannelRequest::MethodId::TRANSPORT_SET_MAX_INCOMING_BITRATE }, - { "transport.setMaxOutgoingBitrate", ChannelRequest::MethodId::TRANSPORT_SET_MAX_OUTGOING_BITRATE }, - { "transport.setMinOutgoingBitrate", ChannelRequest::MethodId::TRANSPORT_SET_MIN_OUTGOING_BITRATE }, - { "transport.restartIce", ChannelRequest::MethodId::TRANSPORT_RESTART_ICE }, - { "transport.produce", ChannelRequest::MethodId::TRANSPORT_PRODUCE }, - { "transport.consume", ChannelRequest::MethodId::TRANSPORT_CONSUME }, - { "transport.produceData", ChannelRequest::MethodId::TRANSPORT_PRODUCE_DATA }, - { "transport.consumeData", ChannelRequest::MethodId::TRANSPORT_CONSUME_DATA }, - { "transport.enableTraceEvent", ChannelRequest::MethodId::TRANSPORT_ENABLE_TRACE_EVENT }, - { "transport.closeProducer", ChannelRequest::MethodId::TRANSPORT_CLOSE_PRODUCER }, - { "transport.closeConsumer", ChannelRequest::MethodId::TRANSPORT_CLOSE_CONSUMER }, - { "transport.closeDataProducer", ChannelRequest::MethodId::TRANSPORT_CLOSE_DATA_PRODUCER }, - { "transport.closeDataConsumer", ChannelRequest::MethodId::TRANSPORT_CLOSE_DATA_CONSUMER }, - { "producer.dump", ChannelRequest::MethodId::PRODUCER_DUMP }, - { "producer.getStats", ChannelRequest::MethodId::PRODUCER_GET_STATS }, - { "producer.pause", ChannelRequest::MethodId::PRODUCER_PAUSE }, - { "producer.resume" , ChannelRequest::MethodId::PRODUCER_RESUME }, - { "producer.enableTraceEvent", ChannelRequest::MethodId::PRODUCER_ENABLE_TRACE_EVENT }, - { "consumer.dump", ChannelRequest::MethodId::CONSUMER_DUMP }, - { "consumer.getStats", ChannelRequest::MethodId::CONSUMER_GET_STATS }, - { "consumer.pause", ChannelRequest::MethodId::CONSUMER_PAUSE }, - { "consumer.resume", ChannelRequest::MethodId::CONSUMER_RESUME }, - { "consumer.setPreferredLayers", ChannelRequest::MethodId::CONSUMER_SET_PREFERRED_LAYERS }, - { "consumer.setPriority", ChannelRequest::MethodId::CONSUMER_SET_PRIORITY }, - { "consumer.requestKeyFrame", ChannelRequest::MethodId::CONSUMER_REQUEST_KEY_FRAME }, - { "consumer.enableTraceEvent", ChannelRequest::MethodId::CONSUMER_ENABLE_TRACE_EVENT }, - { "dataProducer.dump", ChannelRequest::MethodId::DATA_PRODUCER_DUMP }, - { "dataProducer.getStats", ChannelRequest::MethodId::DATA_PRODUCER_GET_STATS }, - { "dataConsumer.dump", ChannelRequest::MethodId::DATA_CONSUMER_DUMP }, - { "dataConsumer.getStats", ChannelRequest::MethodId::DATA_CONSUMER_GET_STATS }, - { "dataConsumer.getBufferedAmount", ChannelRequest::MethodId::DATA_CONSUMER_GET_BUFFERED_AMOUNT }, - { "dataConsumer.setBufferedAmountLowThreshold", ChannelRequest::MethodId::DATA_CONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD }, - { "rtpObserver.pause", ChannelRequest::MethodId::RTP_OBSERVER_PAUSE }, - { "rtpObserver.resume", ChannelRequest::MethodId::RTP_OBSERVER_RESUME }, - { "rtpObserver.addProducer", ChannelRequest::MethodId::RTP_OBSERVER_ADD_PRODUCER }, - { "rtpObserver.removeProducer", ChannelRequest::MethodId::RTP_OBSERVER_REMOVE_PRODUCER } + { FBS::Request::Method::WORKER_CLOSE, "worker.close" }, + { FBS::Request::Method::WORKER_DUMP, "worker.dump" }, + { FBS::Request::Method::WORKER_GET_RESOURCE_USAGE, "worker.getResourceUsage" }, + { FBS::Request::Method::WORKER_UPDATE_SETTINGS, "worker.updateSettings" }, + { FBS::Request::Method::WORKER_CREATE_WEBRTC_SERVER, "worker.createWebRtcServer" }, + { FBS::Request::Method::WORKER_CREATE_ROUTER, "worker.createRouter" }, + { FBS::Request::Method::WORKER_WEBRTC_SERVER_CLOSE, "worker.closeWebRtcServer" }, + { FBS::Request::Method::WORKER_CLOSE_ROUTER, "worker.closeRouter" }, + { FBS::Request::Method::WEBRTC_SERVER_DUMP, "webRtcServer.dump" }, + { FBS::Request::Method::ROUTER_DUMP, "router.dump" }, + { FBS::Request::Method::ROUTER_CREATE_WEBRTC_TRANSPORT, "router.createWebRtcTransport" }, + { FBS::Request::Method::ROUTER_CREATE_WEBRTC_TRANSPORT_WITH_SERVER, "router.createWebRtcTransportWithServer" }, + { FBS::Request::Method::ROUTER_CREATE_PLAIN_TRANSPORT, "router.createPlainTransport" }, + { FBS::Request::Method::ROUTER_CREATE_PIPE_TRANSPORT, "router.createPipeTransport" }, + { FBS::Request::Method::ROUTER_CREATE_DIRECT_TRANSPORT, "router.createDirectTransport" }, + { FBS::Request::Method::ROUTER_CLOSE_TRANSPORT, "router.closeTransport" }, + { FBS::Request::Method::ROUTER_CREATE_ACTIVE_SPEAKER_OBSERVER, "router.createActiveSpeakerObserver" }, + { FBS::Request::Method::ROUTER_CREATE_AUDIO_LEVEL_OBSERVER, "router.createAudioLevelObserver" }, + { FBS::Request::Method::ROUTER_CLOSE_RTP_OBSERVER, "router.closeRtpObserver" }, + { FBS::Request::Method::TRANSPORT_DUMP, "transport.dump" }, + { FBS::Request::Method::TRANSPORT_GET_STATS, "transport.getStats" }, + { FBS::Request::Method::TRANSPORT_CONNECT, "transport.connect" }, + { FBS::Request::Method::TRANSPORT_SET_MAX_INCOMING_BITRATE, "transport.setMaxIncomingBitrate" }, + { FBS::Request::Method::TRANSPORT_SET_MAX_OUTGOING_BITRATE, "transport.setMaxOutgoingBitrate" }, + { FBS::Request::Method::TRANSPORT_SET_MIN_OUTGOING_BITRATE, "transport.setMinOutgoingBitrate" }, + { FBS::Request::Method::TRANSPORT_RESTART_ICE, "transport.restartIce" }, + { FBS::Request::Method::TRANSPORT_PRODUCE, "transport.produce" }, + { FBS::Request::Method::TRANSPORT_PRODUCE_DATA, "transport.produceData" }, + { FBS::Request::Method::TRANSPORT_CONSUME, "transport.consume" }, + { FBS::Request::Method::TRANSPORT_CONSUME_DATA, "transport.consumeData" }, + { FBS::Request::Method::TRANSPORT_ENABLE_TRACE_EVENT, "transport.enableTraceEvent" }, + { FBS::Request::Method::TRANSPORT_CLOSE_PRODUCER, "transport.closeProducer" }, + { FBS::Request::Method::TRANSPORT_CLOSE_CONSUMER, "transport.closeConsumer" }, + { FBS::Request::Method::TRANSPORT_CLOSE_DATA_PRODUCER, "transport.closeDataProducer" }, + { FBS::Request::Method::TRANSPORT_CLOSE_DATA_CONSUMER, "transport.closeDataConsumer" }, + { FBS::Request::Method::PLAIN_TRANSPORT_CONNECT, "plainTransport.connect" }, + { FBS::Request::Method::PIPE_TRANSPORT_CONNECT, "pipeTransport.connect" }, + { FBS::Request::Method::WEBRTC_TRANSPORT_CONNECT, "webRtcTransport.connect" }, + { FBS::Request::Method::PRODUCER_DUMP, "producer.dump" }, + { FBS::Request::Method::PRODUCER_GET_STATS, "producer.getStats" }, + { FBS::Request::Method::PRODUCER_PAUSE, "producer.pause" }, + { FBS::Request::Method::PRODUCER_RESUME, "producer.resume" }, + { FBS::Request::Method::PRODUCER_ENABLE_TRACE_EVENT, "producer.enableTraceEvent" }, + { FBS::Request::Method::CONSUMER_DUMP, "consumer.dump" }, + { FBS::Request::Method::CONSUMER_GET_STATS, "consumer.getStats" }, + { FBS::Request::Method::CONSUMER_PAUSE, "consumer.pause" }, + { FBS::Request::Method::CONSUMER_RESUME, "consumer.resume" }, + { FBS::Request::Method::CONSUMER_SET_PREFERRED_LAYERS, "consumer.setPreferredLayers" }, + { FBS::Request::Method::CONSUMER_SET_PRIORITY, "consumer.setPriority" }, + { FBS::Request::Method::CONSUMER_REQUEST_KEY_FRAME, "consumer.requestKeyFrame" }, + { FBS::Request::Method::CONSUMER_ENABLE_TRACE_EVENT, "consumer.enableTraceEvent" }, + { FBS::Request::Method::DATA_PRODUCER_DUMP, "dataProducer.dump" }, + { FBS::Request::Method::DATA_PRODUCER_GET_STATS, "dataProducer.getStats" }, + { FBS::Request::Method::DATA_CONSUMER_DUMP, "dataConsumer.dump" }, + { FBS::Request::Method::DATA_CONSUMER_GET_STATS, "dataConsumer.getStats" }, + { FBS::Request::Method::DATA_CONSUMER_GET_BUFFERED_AMOUNT, "dataConsumer.getBufferedAmount" }, + { FBS::Request::Method::DATA_CONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD, "dataConsumer.setBufferedAmountLowThreshold" }, + { FBS::Request::Method::DATA_CONSUMER_SEND, "dataConsumer.send" }, + { FBS::Request::Method::RTP_OBSERVER_PAUSE, "rtpObserver.pause" }, + { FBS::Request::Method::RTP_OBSERVER_RESUME, "rtpObserver.resume" }, + { FBS::Request::Method::RTP_OBSERVER_ADD_PRODUCER, "rtpObserver.addProducer" }, + { FBS::Request::Method::RTP_OBSERVER_REMOVE_PRODUCER, "rtpObserver.removeProducer" }, }; // clang-format on /* Instance methods. */ /** - * msg contains "id:method:handlerId:data" where: - * - id: The ID of the request. - * - handlerId: The ID of the target entity - * - data: JSON object. + * msg contains the request flatbuffer. */ - ChannelRequest::ChannelRequest(Channel::ChannelSocket* channel, const char* msg, size_t msgLen) + ChannelRequest::ChannelRequest(Channel::ChannelSocket* channel, const FBS::Request::Request* request) : channel(channel) { MS_TRACE(); - auto info = Utils::String::Split(std::string(msg, msgLen), ':', 3); + this->data = request; + this->id = request->id(); + this->method = request->method(); - if (info.size() < 2) - MS_THROW_ERROR("too few arguments"); + auto methodCStrIt = ChannelRequest::method2String.find(this->method); - this->id = std::stoul(info[0]); - this->method = info[1]; - - auto methodIdIt = ChannelRequest::string2MethodId.find(this->method); - - if (methodIdIt == ChannelRequest::string2MethodId.end()) + if (methodCStrIt == ChannelRequest::method2String.end()) { Error("unknown method"); - MS_THROW_ERROR("unknown method '%s'", this->method.c_str()); - } - - this->methodId = methodIdIt->second; - - if (info.size() > 2) - { - auto& handlerId = info[2]; - - if (handlerId != "undefined") - this->handlerId = handlerId; + MS_THROW_ERROR("unknown method '%" PRIu8 "'", this->method); } - if (info.size() > 3) - { - auto& data = info[3]; - - if (data != "undefined") - { - try - { - this->data = json::parse(data); - - if (!this->data.is_object()) - this->data = json::object(); - } - catch (const json::parse_error& error) - { - MS_THROW_TYPE_ERROR("JSON parsing error: %s", error.what()); - } - } - } - } + this->methodCStr = methodCStrIt->second; - ChannelRequest::~ChannelRequest() - { - MS_TRACE(); + // Handler ID is optional. + if (flatbuffers::IsFieldPresent(this->data, FBS::Request::Request::VT_HANDLERID)) + this->handlerId = this->data->handlerId()->str(); } void ChannelRequest::Accept() @@ -148,31 +115,11 @@ namespace Channel this->replied = true; - std::string response("{\"id\":"); + auto& builder = this->bufferBuilder; + auto response = + FBS::Response::CreateResponse(builder, this->id, true, FBS::Response::Body::NONE, 0); - response.append(std::to_string(this->id)); - response.append(",\"accepted\":true}"); - - this->channel->Send(response); - } - - void ChannelRequest::Accept(json& data) - { - MS_TRACE(); - - MS_ASSERT(!this->replied, "request already replied"); - - this->replied = true; - - json jsonResponse = json::object(); - - jsonResponse["id"] = this->id; - jsonResponse["accepted"] = true; - - if (data.is_structured()) - jsonResponse["data"] = data; - - this->channel->Send(jsonResponse); + this->SendResponse(response); } void ChannelRequest::Error(const char* reason) @@ -183,15 +130,11 @@ namespace Channel this->replied = true; - json jsonResponse = json::object(); - - jsonResponse["id"] = this->id; - jsonResponse["error"] = "Error"; + auto& builder = this->bufferBuilder; + auto response = FBS::Response::CreateResponseDirect( + builder, this->id, false /*accepted*/, FBS::Response::Body::NONE, 0, "Error" /*Error*/, reason); - if (reason != nullptr) - jsonResponse["reason"] = reason; - - this->channel->Send(jsonResponse); + this->SendResponse(response); } void ChannelRequest::TypeError(const char* reason) @@ -202,14 +145,29 @@ namespace Channel this->replied = true; - json jsonResponse = json::object(); + auto& builder = this->bufferBuilder; + auto response = FBS::Response::CreateResponseDirect( + builder, this->id, false /*accepted*/, FBS::Response::Body::NONE, 0, "TypeError" /*Error*/, reason); - jsonResponse["id"] = this->id; - jsonResponse["error"] = "TypeError"; + this->SendResponse(response); + } - if (reason != nullptr) - jsonResponse["reason"] = reason; + void ChannelRequest::Send(uint8_t* buffer, size_t size) + { + this->channel->Send(buffer, size); + } - this->channel->Send(jsonResponse); + void ChannelRequest::SendResponse(const flatbuffers::Offset& response) + { + auto& builder = this->bufferBuilder; + auto message = FBS::Message::CreateMessage( + builder, + FBS::Message::Type::RESPONSE, + FBS::Message::Body::FBS_Response_Response, + response.Union()); + + builder.FinishSizePrefixed(message); + this->Send(builder.GetBufferPointer(), builder.GetSize()); + builder.Reset(); } } // namespace Channel diff --git a/worker/src/Channel/ChannelSocket.cpp b/worker/src/Channel/ChannelSocket.cpp index 22bc0a4b69..08261a1e5b 100644 --- a/worker/src/Channel/ChannelSocket.cpp +++ b/worker/src/Channel/ChannelSocket.cpp @@ -5,7 +5,6 @@ #include "DepLibUV.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" -#include // std::ceil() #include // std::memcpy(), std::memmove() namespace Channel @@ -33,8 +32,7 @@ namespace Channel ChannelSocket::ChannelSocket(int consumerFd, int producerFd) : consumerSocket(new ConsumerSocket(consumerFd, MessageMaxLen, this)), - producerSocket(new ProducerSocket(producerFd, MessageMaxLen)), - writeBuffer(static_cast(std::malloc(MessageMaxLen))) + producerSocket(new ProducerSocket(producerFd, MessageMaxLen)) { MS_TRACE_STD(); } @@ -80,8 +78,6 @@ namespace Channel { MS_TRACE_STD(); - std::free(this->writeBuffer); - if (!this->closed) Close(); @@ -121,45 +117,24 @@ namespace Channel this->listener = listener; } - void ChannelSocket::Send(json& jsonMessage) + void ChannelSocket::Send(const uint8_t* message, uint32_t messageLen) { MS_TRACE_STD(); if (this->closed) return; - std::string message = jsonMessage.dump(); - - if (message.length() > PayloadMaxLen) - { - MS_ERROR_STD("message too big"); - - return; - } - - SendImpl( - reinterpret_cast(message.c_str()), static_cast(message.length())); - } - - void ChannelSocket::Send(const std::string& message) - { - MS_TRACE_STD(); - - if (this->closed) - return; - - if (message.length() > PayloadMaxLen) + if (messageLen > PayloadMaxLen) { MS_ERROR_STD("message too big"); return; } - SendImpl( - reinterpret_cast(message.c_str()), static_cast(message.length())); + SendImpl(reinterpret_cast(message), messageLen); } - void ChannelSocket::SendLog(const char* message, uint32_t messageLen) + void ChannelSocket::SendLog(const char* msg, uint32_t messageLen) { MS_TRACE_STD(); @@ -173,7 +148,13 @@ namespace Channel return; } - SendImpl(reinterpret_cast(message), messageLen); + auto log = FBS::Log::CreateLogDirect(this->bufferBuilder, msg); + auto message = FBS::Message::CreateMessage( + this->bufferBuilder, FBS::Message::Type::LOG, FBS::Message::Body::FBS_Log_Log, log.Union()); + + this->bufferBuilder.FinishSizePrefixed(message); + this->Send(this->bufferBuilder.GetBufferPointer(), this->bufferBuilder.GetSize()); + this->bufferBuilder.Reset(); } bool ChannelSocket::CallbackRead() @@ -183,28 +164,34 @@ namespace Channel if (this->closed) return false; - uint8_t* message{ nullptr }; - uint32_t messageLen; - size_t messageCtx; + uint8_t* msg{ nullptr }; + uint32_t msgLen; + size_t msgCtx; // Try to read next message using `channelReadFn`, message, its length and context will be // stored in provided arguments. - auto free = this->channelReadFn( - &message, &messageLen, &messageCtx, this->uvReadHandle, this->channelReadCtx); + auto free = this->channelReadFn(&msg, &msgLen, &msgCtx, this->uvReadHandle, this->channelReadCtx); // Non-null free function pointer means message was successfully read above and will need to be // freed later. if (free) { - try - { - char* charMessage{ reinterpret_cast(message) }; + const auto* message = FBS::Message::GetMessage(msg); - auto* request = new Channel::ChannelRequest(this, charMessage, messageLen); + // TMP: For debugging. + auto s = flatbuffers::FlatBufferToString( + reinterpret_cast(msg), FBS::Message::MessageTypeTable()); + MS_ERROR("%s", s.c_str()); + + if (message->type() == FBS::Message::Type::REQUEST) + { + ChannelRequest* request; - // Notify the listener. try { + request = new ChannelRequest(this, message->data_as()); + + // Notify the listener. this->listener->HandleRequest(request); } catch (const MediaSoupTypeError& error) @@ -216,20 +203,33 @@ namespace Channel request->Error(error.what()); } - // Delete the Request. delete request; } - catch (const json::parse_error& error) + else if (message->type() == FBS::Message::Type::NOTIFICATION) { - MS_ERROR_STD("message parsing error: %s", error.what()); + ChannelNotification* notification; + + try + { + notification = new ChannelNotification(message->data_as()); + + // Notify the listener. + this->listener->HandleNotification(notification); + } + catch (const MediaSoupError& error) + { + MS_ERROR("notification failed: %s", error.what()); + } + + delete notification; } - catch (const MediaSoupError& error) + else { - MS_ERROR_STD("discarding wrong Channel request: %s", error.what()); + MS_ERROR("discarding wrong Channel data"); } // Message needs to be freed using stored function pointer. - free(message, messageLen, messageCtx); + free(msg, msgLen, msgCtx); } // Return `true` if something was processed. @@ -247,30 +247,30 @@ namespace Channel } else { - std::memcpy(this->writeBuffer, &payloadLen, sizeof(uint32_t)); - - if (payloadLen != 0) - { - std::memcpy(this->writeBuffer + sizeof(uint32_t), payload, payloadLen); - } - - size_t len = sizeof(uint32_t) + payloadLen; - - this->producerSocket->Write(this->writeBuffer, len); + this->producerSocket->Write(payload, payloadLen); } } void ChannelSocket::OnConsumerSocketMessage(ConsumerSocket* /*consumerSocket*/, char* msg, size_t msgLen) { - MS_TRACE_STD(); + MS_TRACE(); + + auto* message = FBS::Message::GetMessage(msg); - try + // TMP: For debugging. + // auto s = flatbuffers::FlatBufferToString( + // reinterpret_cast(msg), FBS::Message::MessageTypeTable()); + // MS_ERROR("%s", s.c_str()); + + if (message->type() == FBS::Message::Type::REQUEST) { - auto* request = new Channel::ChannelRequest(this, msg, msgLen); + ChannelRequest* request; - // Notify the listener. try { + request = new ChannelRequest(this, message->data_as()); + + // Notify the listener. this->listener->HandleRequest(request); } catch (const MediaSoupTypeError& error) @@ -282,16 +282,29 @@ namespace Channel request->Error(error.what()); } - // Delete the Request. delete request; } - catch (const json::parse_error& error) + else if (message->type() == FBS::Message::Type::NOTIFICATION) { - MS_ERROR_STD("JSON parsing error: %s", error.what()); + ChannelNotification* notification; + + try + { + notification = new ChannelNotification(message->data_as()); + + // Notify the listener. + this->listener->HandleNotification(notification); + } + catch (const MediaSoupError& error) + { + MS_ERROR("notification failed: %s", error.what()); + } + + delete notification; } - catch (const MediaSoupError& error) + else { - MS_ERROR_STD("discarding wrong Channel request: %s", error.what()); + MS_ERROR("discarding wrong Channel data"); } } diff --git a/worker/src/ChannelMessageRegistrator.cpp b/worker/src/ChannelMessageRegistrator.cpp index 4f5c9bbe50..647994d35c 100644 --- a/worker/src/ChannelMessageRegistrator.cpp +++ b/worker/src/ChannelMessageRegistrator.cpp @@ -15,54 +15,38 @@ ChannelMessageRegistrator::~ChannelMessageRegistrator() MS_TRACE(); this->mapChannelRequestHandlers.clear(); - this->mapPayloadChannelRequestHandlers.clear(); - this->mapPayloadChannelNotificationHandlers.clear(); + this->mapChannelNotificationHandlers.clear(); } -void ChannelMessageRegistrator::FillJson(json& jsonObject) +flatbuffers::Offset ChannelMessageRegistrator::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) { - MS_TRACE(); - - // Add channelRequestHandlers. - jsonObject["channelRequestHandlers"] = json::array(); - auto jsonChannelRequestHandlersIt = jsonObject.find("channelRequestHandlers"); - + // Add channelRequestHandlerIds. + std::vector> channelRequestHandlerIds; for (const auto& kv : this->mapChannelRequestHandlers) { const auto& handlerId = kv.first; - jsonChannelRequestHandlersIt->emplace_back(handlerId); + channelRequestHandlerIds.push_back(builder.CreateString(handlerId)); } - // Add payloadChannelRequestHandlers. - jsonObject["payloadChannelRequestHandlers"] = json::array(); - auto jsonPayloadChannelRequestHandlersIt = jsonObject.find("payloadChannelRequestHandlers"); - - for (const auto& kv : this->mapPayloadChannelRequestHandlers) + // Add channelNotificationHandlerIds. + std::vector> channelNotificationHandlerIds; + for (const auto& kv : this->mapChannelNotificationHandlers) { const auto& handlerId = kv.first; - jsonPayloadChannelRequestHandlersIt->emplace_back(handlerId); + channelNotificationHandlerIds.push_back(builder.CreateString(handlerId)); } - // Add payloadChannelNotificationHandlers. - jsonObject["payloadChannelNotificationHandlers"] = json::array(); - auto jsonPayloadChannelNotificationHandlersIt = - jsonObject.find("payloadChannelNotificationHandlers"); - - for (const auto& kv : this->mapPayloadChannelNotificationHandlers) - { - const auto& handlerId = kv.first; - - jsonPayloadChannelNotificationHandlersIt->emplace_back(handlerId); - } + return FBS::Worker::CreateChannelMessageHandlersDirect( + builder, &channelRequestHandlerIds, &channelNotificationHandlerIds); } void ChannelMessageRegistrator::RegisterHandler( const std::string& id, Channel::ChannelSocket::RequestHandler* channelRequestHandler, - PayloadChannel::PayloadChannelSocket::RequestHandler* payloadChannelRequestHandler, - PayloadChannel::PayloadChannelSocket::NotificationHandler* payloadChannelNotificationHandler) + Channel::ChannelSocket::NotificationHandler* channelNotificationHandler) { MS_TRACE(); @@ -76,41 +60,19 @@ void ChannelMessageRegistrator::RegisterHandler( this->mapChannelRequestHandlers[id] = channelRequestHandler; } - if (payloadChannelRequestHandler != nullptr) - { - if (this->mapPayloadChannelRequestHandlers.find(id) != this->mapPayloadChannelRequestHandlers.end()) - { - if (channelRequestHandler != nullptr) - { - this->mapChannelRequestHandlers.erase(id); - } - - MS_THROW_ERROR("PayloadChannel request handler with ID %s already exists", id.c_str()); - } - - this->mapPayloadChannelRequestHandlers[id] = payloadChannelRequestHandler; - } - - if (payloadChannelNotificationHandler != nullptr) + if (channelNotificationHandler != nullptr) { - if ( - this->mapPayloadChannelNotificationHandlers.find(id) != - this->mapPayloadChannelNotificationHandlers.end()) + if (this->mapChannelNotificationHandlers.find(id) != this->mapChannelNotificationHandlers.end()) { if (channelRequestHandler != nullptr) { this->mapChannelRequestHandlers.erase(id); } - if (payloadChannelRequestHandler != nullptr) - { - this->mapPayloadChannelRequestHandlers.erase(id); - } - - MS_THROW_ERROR("PayloadChannel notification handler with ID %s already exists", id.c_str()); + MS_THROW_ERROR("Channel notification handler with ID %s already exists", id.c_str()); } - this->mapPayloadChannelNotificationHandlers[id] = payloadChannelNotificationHandler; + this->mapChannelNotificationHandlers[id] = channelNotificationHandler; } } @@ -119,8 +81,7 @@ void ChannelMessageRegistrator::UnregisterHandler(const std::string& id) MS_TRACE(); this->mapChannelRequestHandlers.erase(id); - this->mapPayloadChannelRequestHandlers.erase(id); - this->mapPayloadChannelNotificationHandlers.erase(id); + this->mapChannelNotificationHandlers.erase(id); } Channel::ChannelSocket::RequestHandler* ChannelMessageRegistrator::GetChannelRequestHandler( @@ -140,31 +101,14 @@ Channel::ChannelSocket::RequestHandler* ChannelMessageRegistrator::GetChannelReq } } -PayloadChannel::PayloadChannelSocket::RequestHandler* ChannelMessageRegistrator::GetPayloadChannelRequestHandler( +Channel::ChannelSocket::NotificationHandler* ChannelMessageRegistrator::GetChannelNotificationHandler( const std::string& id) { MS_TRACE(); - auto it = this->mapPayloadChannelRequestHandlers.find(id); - - if (it != this->mapPayloadChannelRequestHandlers.end()) - { - return it->second; - } - else - { - return nullptr; - } -} - -PayloadChannel::PayloadChannelSocket::NotificationHandler* ChannelMessageRegistrator:: - GetPayloadChannelNotificationHandler(const std::string& id) -{ - MS_TRACE(); - - auto it = this->mapPayloadChannelNotificationHandlers.find(id); + auto it = this->mapChannelNotificationHandlers.find(id); - if (it != this->mapPayloadChannelNotificationHandlers.end()) + if (it != this->mapChannelNotificationHandlers.end()) { return it->second; } diff --git a/worker/src/PayloadChannel/PayloadChannelNotification.cpp b/worker/src/PayloadChannel/PayloadChannelNotification.cpp deleted file mode 100644 index 8805323d6d..0000000000 --- a/worker/src/PayloadChannel/PayloadChannelNotification.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#define MS_CLASS "PayloadChannel::PayloadChannelNotification" -// #define MS_LOG_DEV_LEVEL 3 - -#include "PayloadChannel/PayloadChannelNotification.hpp" -#include "Logger.hpp" -#include "MediaSoupErrors.hpp" -#include "Utils.hpp" - -namespace PayloadChannel -{ - /* Class variables. */ - - // clang-format off - absl::flat_hash_map PayloadChannelNotification::string2EventId = - { - { "transport.sendRtcp", PayloadChannelNotification::EventId::TRANSPORT_SEND_RTCP }, - { "producer.send", PayloadChannelNotification::EventId::PRODUCER_SEND }, - { "dataProducer.send", PayloadChannelNotification::EventId::DATA_PRODUCER_SEND } - }; - // clang-format on - - /* Class methods. */ - - bool PayloadChannelNotification::IsNotification(const char* msg, size_t msgLen) - { - MS_TRACE(); - - return (msgLen > 2 && msg[0] == 'n' && msg[1] == ':'); - } - - /* Instance methods. */ - - PayloadChannelNotification::PayloadChannelNotification(const char* msg, size_t msgLen) - { - MS_TRACE(); - - auto info = Utils::String::Split(std::string(msg, msgLen), ':'); - - if (info.size() < 1) - MS_THROW_ERROR("too few arguments"); - - this->event = info[0]; - - auto eventIdIt = PayloadChannelNotification::string2EventId.find(this->event); - - if (eventIdIt == PayloadChannelNotification::string2EventId.end()) - MS_THROW_ERROR("unknown event '%s'", this->event.c_str()); - - this->eventId = eventIdIt->second; - - if (info.size() > 1) - { - auto& handlerId = info[1]; - - if (handlerId != "undefined") - this->handlerId = handlerId; - } - - if (info.size() > 2) - { - auto& data = info[2]; - - if (data != "undefined") - this->data = data; - } - } - - PayloadChannelNotification::~PayloadChannelNotification() - { - MS_TRACE(); - } - - void PayloadChannelNotification::SetPayload(const uint8_t* payload, size_t payloadLen) - { - MS_TRACE(); - - this->payload = payload; - this->payloadLen = payloadLen; - } -} // namespace PayloadChannel diff --git a/worker/src/PayloadChannel/PayloadChannelNotifier.cpp b/worker/src/PayloadChannel/PayloadChannelNotifier.cpp deleted file mode 100644 index 57090ff80d..0000000000 --- a/worker/src/PayloadChannel/PayloadChannelNotifier.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#define MS_CLASS "PayloadChannel::Notifier" -// #define MS_LOG_DEV_LEVEL 3 - -#include "PayloadChannel/PayloadChannelNotifier.hpp" -#include "Logger.hpp" - -namespace PayloadChannel -{ - PayloadChannelNotifier::PayloadChannelNotifier(PayloadChannel::PayloadChannelSocket* payloadChannel) - : payloadChannel(payloadChannel) - { - MS_TRACE(); - } - - void PayloadChannelNotifier::Emit( - const std::string& targetId, const char* event, const uint8_t* payload, size_t payloadLen) - { - MS_TRACE(); - - std::string notification("{\"targetId\":\""); - - notification.append(targetId); - notification.append("\",\"event\":\""); - notification.append(event); - notification.append("\"}"); - - this->payloadChannel->Send(notification, payload, payloadLen); - } - - void PayloadChannelNotifier::Emit( - const std::string& targetId, const char* event, json& data, const uint8_t* payload, size_t payloadLen) - { - MS_TRACE(); - - json jsonNotification = json::object(); - - jsonNotification["targetId"] = targetId; - jsonNotification["event"] = event; - jsonNotification["data"] = data; - - this->payloadChannel->Send(jsonNotification, payload, payloadLen); - } -} // namespace PayloadChannel diff --git a/worker/src/PayloadChannel/PayloadChannelRequest.cpp b/worker/src/PayloadChannel/PayloadChannelRequest.cpp deleted file mode 100644 index 9e074695d2..0000000000 --- a/worker/src/PayloadChannel/PayloadChannelRequest.cpp +++ /dev/null @@ -1,165 +0,0 @@ -#define MS_CLASS "PayloadChannel::PayloadChannelRequest" -// #define MS_LOG_DEV_LEVEL 3 - -#include "PayloadChannel/PayloadChannelRequest.hpp" -#include "Logger.hpp" -#include "MediaSoupErrors.hpp" -#include "Utils.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" - -namespace PayloadChannel -{ - /* Class variables. */ - - // clang-format off - absl::flat_hash_map PayloadChannelRequest::string2MethodId = - { - { "dataConsumer.send", PayloadChannelRequest::MethodId::DATA_CONSUMER_SEND }, - }; - // clang-format on - - /* Class methods. */ - - bool PayloadChannelRequest::IsRequest(const char* msg, size_t msgLen) - { - MS_TRACE(); - - return (msgLen > 2 && msg[0] == 'r' && msg[1] == ':'); - } - - /* Instance methods. */ - - /** - * msg contains "id:method:handlerId:data" where: - * - id: The ID of the request. - * - handlerId: The ID of the target entity - * - data: JSON object. - */ - PayloadChannelRequest::PayloadChannelRequest( - PayloadChannel::PayloadChannelSocket* channel, char* msg, size_t msgLen) - : channel(channel) - { - MS_TRACE(); - - auto info = Utils::String::Split(std::string(msg, msgLen), ':', 3); - - if (info.size() < 2) - MS_THROW_ERROR("too few arguments"); - - this->id = std::stoul(info[0]); - this->method = info[1]; - - auto methodIdIt = PayloadChannelRequest::string2MethodId.find(this->method); - - if (methodIdIt == PayloadChannelRequest::string2MethodId.end()) - { - Error("unknown method"); - - MS_THROW_ERROR("unknown method '%s'", this->method.c_str()); - } - - this->methodId = methodIdIt->second; - - if (info.size() > 2) - { - auto& handlerId = info[2]; - - if (handlerId != "undefined") - this->handlerId = handlerId; - } - - if (info.size() > 3) - { - auto& data = info[3]; - - if (data != "undefined") - this->data = data; - } - } - - PayloadChannelRequest::~PayloadChannelRequest() - { - MS_TRACE(); - } - - void PayloadChannelRequest::Accept() - { - MS_TRACE(); - - MS_ASSERT(!this->replied, "request already replied"); - - this->replied = true; - - std::string response("{\"id\":"); - - response.append(std::to_string(this->id)); - response.append(",\"accepted\":true}"); - - this->channel->Send(response); - } - - void PayloadChannelRequest::Accept(json& data) - { - MS_TRACE(); - - MS_ASSERT(!this->replied, "request already replied"); - - this->replied = true; - - json jsonResponse = json::object(); - - jsonResponse["id"] = this->id; - jsonResponse["accepted"] = true; - - if (data.is_structured()) - jsonResponse["data"] = data; - - this->channel->Send(jsonResponse); - } - - void PayloadChannelRequest::Error(const char* reason) - { - MS_TRACE(); - - MS_ASSERT(!this->replied, "request already replied"); - - this->replied = true; - - json jsonResponse = json::object(); - - jsonResponse["id"] = this->id; - jsonResponse["error"] = "Error"; - - if (reason != nullptr) - jsonResponse["reason"] = reason; - - this->channel->Send(jsonResponse); - } - - void PayloadChannelRequest::TypeError(const char* reason) - { - MS_TRACE(); - - MS_ASSERT(!this->replied, "request already replied"); - - this->replied = true; - - json jsonResponse = json::object(); - - jsonResponse["id"] = this->id; - jsonResponse["error"] = "TypeError"; - - if (reason != nullptr) - jsonResponse["reason"] = reason; - - this->channel->Send(jsonResponse); - } - - void PayloadChannelRequest::SetPayload(const uint8_t* payload, size_t payloadLen) - { - MS_TRACE(); - - this->payload = payload; - this->payloadLen = payloadLen; - } -} // namespace PayloadChannel diff --git a/worker/src/PayloadChannel/PayloadChannelSocket.cpp b/worker/src/PayloadChannel/PayloadChannelSocket.cpp deleted file mode 100644 index 52ba754f06..0000000000 --- a/worker/src/PayloadChannel/PayloadChannelSocket.cpp +++ /dev/null @@ -1,538 +0,0 @@ -#define MS_CLASS "PayloadChannel::PayloadChannelSocket" -// #define MS_LOG_DEV_LEVEL 3 - -#include "PayloadChannel/PayloadChannelSocket.hpp" -#include "DepLibUV.hpp" -#include "Logger.hpp" -#include "MediaSoupErrors.hpp" -#include "PayloadChannel/PayloadChannelRequest.hpp" -#include // std::ceil() -#include // std::memcpy(), std::memmove() - -namespace PayloadChannel -{ - // Binary length for a 4194304 bytes payload. - static constexpr size_t MessageMaxLen{ 4194308 }; - static constexpr size_t PayloadMaxLen{ 4194304 }; - - /* Static methods for UV callbacks. */ - - inline static void onAsync(uv_handle_t* handle) - { - while (static_cast(handle->data)->CallbackRead()) - { - // Read while there are new messages. - } - } - - inline static void onClose(uv_handle_t* handle) - { - delete handle; - } - - /* Instance methods. */ - - PayloadChannelSocket::PayloadChannelSocket(int consumerFd, int producerFd) - : consumerSocket(new ConsumerSocket(consumerFd, MessageMaxLen, this)), - producerSocket(new ProducerSocket(producerFd, MessageMaxLen)), - writeBuffer(static_cast(std::malloc(MessageMaxLen))) - { - MS_TRACE(); - } - - PayloadChannelSocket::PayloadChannelSocket( - PayloadChannelReadFn payloadChannelReadFn, - PayloadChannelReadCtx payloadChannelReadCtx, - PayloadChannelWriteFn payloadChannelWriteFn, - PayloadChannelWriteCtx payloadChannelWriteCtx) - : payloadChannelReadFn(payloadChannelReadFn), payloadChannelReadCtx(payloadChannelReadCtx), - payloadChannelWriteFn(payloadChannelWriteFn), payloadChannelWriteCtx(payloadChannelWriteCtx) - { - MS_TRACE(); - - int err; - - this->uvReadHandle = new uv_async_t; - this->uvReadHandle->data = static_cast(this); - - err = - uv_async_init(DepLibUV::GetLoop(), this->uvReadHandle, reinterpret_cast(onAsync)); - - if (err != 0) - { - delete this->uvReadHandle; - this->uvReadHandle = nullptr; - - MS_THROW_ERROR("uv_async_init() failed: %s", uv_strerror(err)); - } - - err = uv_async_send(this->uvReadHandle); - - if (err != 0) - { - delete this->uvReadHandle; - this->uvReadHandle = nullptr; - - MS_THROW_ERROR("uv_async_send() failed: %s", uv_strerror(err)); - } - } - - PayloadChannelSocket::~PayloadChannelSocket() - { - MS_TRACE(); - - std::free(this->writeBuffer); - delete this->ongoingNotification; - - if (!this->closed) - Close(); - - delete this->consumerSocket; - delete this->producerSocket; - } - - void PayloadChannelSocket::Close() - { - MS_TRACE_STD(); - - if (this->closed) - return; - - this->closed = true; - - if (this->uvReadHandle) - { - uv_close(reinterpret_cast(this->uvReadHandle), static_cast(onClose)); - } - - if (this->consumerSocket) - { - this->consumerSocket->Close(); - } - - if (this->producerSocket) - { - this->producerSocket->Close(); - } - } - - void PayloadChannelSocket::SetListener(Listener* listener) - { - MS_TRACE(); - - this->listener = listener; - } - - void PayloadChannelSocket::Send(json& jsonMessage, const uint8_t* payload, size_t payloadLen) - { - MS_TRACE(); - - if (this->closed) - return; - - std::string message = jsonMessage.dump(); - - this->Send(message, payload, payloadLen); - } - - void PayloadChannelSocket::Send(const std::string& message, const uint8_t* payload, size_t payloadLen) - { - MS_TRACE(); - - if (this->closed) - return; - - if (message.length() > PayloadMaxLen) - { - MS_ERROR("message too big"); - - return; - } - else if (payloadLen > PayloadMaxLen) - { - MS_ERROR("payload too big"); - - return; - } - - SendImpl( - reinterpret_cast(message.c_str()), - static_cast(message.length()), - payload, - static_cast(payloadLen)); - } - - void PayloadChannelSocket::Send(json& jsonMessage) - { - MS_TRACE_STD(); - - if (this->closed) - return; - - std::string message = jsonMessage.dump(); - - if (message.length() > PayloadMaxLen) - { - MS_ERROR_STD("message too big"); - - return; - } - - SendImpl( - reinterpret_cast(message.c_str()), static_cast(message.length())); - } - - void PayloadChannelSocket::Send(const std::string& message) - { - MS_TRACE(); - - if (this->closed) - return; - - if (message.length() > PayloadMaxLen) - { - MS_ERROR("message too big"); - - return; - } - - SendImpl( - reinterpret_cast(message.c_str()), static_cast(message.length())); - } - - bool PayloadChannelSocket::CallbackRead() - { - MS_TRACE(); - - if (this->closed) - return false; - - uint8_t* message{ nullptr }; - uint32_t messageLen; - size_t messageCtx; - - uint8_t* payload{ nullptr }; - uint32_t payloadLen; - size_t payloadCapacity; - - // Try to read next message and payload using `payloadChannelReadFn`, message and payload, - // alongside their lengths and contexts will be stored in provided arguments. - auto free = this->payloadChannelReadFn( - &message, - &messageLen, - &messageCtx, - &payload, - &payloadLen, - &payloadCapacity, - this->uvReadHandle, - this->payloadChannelReadCtx); - - // Non-null free function pointer means message was successfully read above and will need to be - // freed later. - if (free) - { - try - { - char* charMessage{ reinterpret_cast(message) }; - - if (PayloadChannelRequest::IsRequest(charMessage, messageLen)) - { - try - { - auto* request = - new PayloadChannel::PayloadChannelRequest(this, charMessage + 2, messageLen - 2); - request->SetPayload(payload, payloadLen); - - // Notify the listener. - try - { - this->listener->HandleRequest(request); - } - catch (const MediaSoupTypeError& error) - { - request->TypeError(error.what()); - } - catch (const MediaSoupError& error) - { - request->Error(error.what()); - } - - // Delete the Request. - delete request; - } - catch (const json::parse_error& error) - { - MS_ERROR_STD("message parsing error: %s", error.what()); - } - catch (const MediaSoupError& error) - { - MS_ERROR("discarding wrong PayloadChannel request: %s", error.what()); - } - } - - else if (PayloadChannelNotification::IsNotification(charMessage, messageLen)) - { - try - { - auto* notification = - new PayloadChannel::PayloadChannelNotification(charMessage + 2, messageLen - 2); - notification->SetPayload(payload, payloadLen); - - // Notify the listener. - try - { - this->listener->HandleNotification(notification); - } - catch (const MediaSoupError& error) - { - MS_ERROR("notification failed: %s", error.what()); - } - - // Delete the Notification. - delete notification; - } - catch (const json::parse_error& error) - { - MS_ERROR_STD("message parsing error: %s", error.what()); - } - catch (const MediaSoupError& error) - { - MS_ERROR("discarding wrong PayloadChannel notification: %s", error.what()); - } - } - - else - { - MS_ERROR("discarding wrong PayloadChannel data"); - } - } - catch (const json::parse_error& error) - { - MS_ERROR("JSON parsing error: %s", error.what()); - } - catch (const MediaSoupError& error) - { - MS_ERROR("discarding wrong Channel request: %s", error.what()); - } - - // Message and payload need to be freed using stored function pointer. - free(message, messageLen, messageCtx); - free(payload, payloadLen, payloadCapacity); - } - - // Return `true` if something was processed. - return free != nullptr; - } - - inline void PayloadChannelSocket::SendImpl(const uint8_t* message, uint32_t messageLen) - { - MS_TRACE(); - - // Write using function call if provided. - if (this->payloadChannelWriteFn) - { - this->payloadChannelWriteFn(message, messageLen, nullptr, 0, this->payloadChannelWriteCtx); - } - else - { - std::memcpy(this->writeBuffer, &messageLen, sizeof(uint32_t)); - - if (messageLen != 0) - { - std::memcpy(this->writeBuffer + sizeof(uint32_t), message, messageLen); - } - - size_t len = sizeof(uint32_t) + messageLen; - - this->producerSocket->Write(this->writeBuffer, len); - } - } - - inline void PayloadChannelSocket::SendImpl( - const uint8_t* message, uint32_t messageLen, const uint8_t* payload, uint32_t payloadLen) - { - MS_TRACE(); - - // Write using function call if provided. - if (this->payloadChannelWriteFn) - { - this->payloadChannelWriteFn( - message, messageLen, payload, payloadLen, this->payloadChannelWriteCtx); - } - else - { - SendImpl(message, messageLen); - SendImpl(payload, payloadLen); - } - } - - void PayloadChannelSocket::OnConsumerSocketMessage( - ConsumerSocket* /*consumerSocket*/, char* msg, size_t msgLen) - { - MS_TRACE(); - - if (!this->ongoingNotification && !this->ongoingRequest) - { - if (PayloadChannelRequest::IsRequest(msg, msgLen)) - { - try - { - this->ongoingRequest = new PayloadChannel::PayloadChannelRequest(this, msg + 2, msgLen - 2); - } - catch (const json::parse_error& error) - { - MS_ERROR_STD("msg parsing error: %s", error.what()); - } - catch (const MediaSoupError& error) - { - MS_ERROR("discarding wrong PayloadChannel request: %s", error.what()); - } - } - else if (PayloadChannelNotification::IsNotification(msg, msgLen)) - { - try - { - this->ongoingNotification = - new PayloadChannel::PayloadChannelNotification(msg + 2, msgLen - 2); - } - catch (const json::parse_error& error) - { - MS_ERROR_STD("msg parsing error: %s", error.what()); - } - catch (const MediaSoupError& error) - { - MS_ERROR("discarding wrong PayloadChannel notification: %s", error.what()); - } - } - else - { - MS_ERROR("discarding wrong PayloadChannel data"); - } - } - else if (this->ongoingNotification) - { - this->ongoingNotification->SetPayload(reinterpret_cast(msg), msgLen); - - // Notify the listener. - try - { - this->listener->HandleNotification(this->ongoingNotification); - } - catch (const MediaSoupError& error) - { - MS_ERROR("notification failed: %s", error.what()); - } - - // Delete the Notification. - delete this->ongoingNotification; - this->ongoingNotification = nullptr; - } - else if (this->ongoingRequest) - { - this->ongoingRequest->SetPayload(reinterpret_cast(msg), msgLen); - - // Notify the listener. - try - { - this->listener->HandleRequest(this->ongoingRequest); - } - catch (const MediaSoupTypeError& error) - { - this->ongoingRequest->TypeError(error.what()); - } - catch (const MediaSoupError& error) - { - this->ongoingRequest->Error(error.what()); - } - - // Delete the Request. - delete this->ongoingRequest; - this->ongoingRequest = nullptr; - } - } - - void PayloadChannelSocket::OnConsumerSocketClosed(ConsumerSocket* /*consumerSocket*/) - { - MS_TRACE(); - - this->listener->OnPayloadChannelClosed(this); - } - - /* Instance methods. */ - - ConsumerSocket::ConsumerSocket(int fd, size_t bufferSize, Listener* listener) - : ::UnixStreamSocket(fd, bufferSize, ::UnixStreamSocket::Role::CONSUMER), listener(listener) - { - MS_TRACE(); - } - - ConsumerSocket::~ConsumerSocket() - { - MS_TRACE(); - } - - void ConsumerSocket::UserOnUnixStreamRead() - { - MS_TRACE(); - - size_t msgStart{ 0 }; - - // Be ready to parse more than a single message in a single chunk. - while (true) - { - if (IsClosed()) - return; - - size_t readLen = this->bufferDataLen - msgStart; - - if (readLen < sizeof(uint32_t)) - { - // Incomplete data. - break; - } - - uint32_t msgLen; - // Read message length. - std::memcpy(&msgLen, this->buffer + msgStart, sizeof(uint32_t)); - - if (readLen < sizeof(uint32_t) + static_cast(msgLen)) - { - // Incomplete data. - break; - } - - this->listener->OnConsumerSocketMessage( - this, - reinterpret_cast(this->buffer + msgStart + sizeof(uint32_t)), - static_cast(msgLen)); - - msgStart += sizeof(uint32_t) + static_cast(msgLen); - } - - if (msgStart != 0) - { - this->bufferDataLen = this->bufferDataLen - msgStart; - - if (this->bufferDataLen != 0) - { - std::memmove(this->buffer, this->buffer + msgStart, this->bufferDataLen); - } - } - } - - void ConsumerSocket::UserOnUnixStreamSocketClosed() - { - MS_TRACE(); - - // Notify the listener. - this->listener->OnConsumerSocketClosed(this); - } - - /* Instance methods. */ - - ProducerSocket::ProducerSocket(int fd, size_t bufferSize) - : ::UnixStreamSocket(fd, bufferSize, ::UnixStreamSocket::Role::PRODUCER) - { - MS_TRACE(); - } -} // namespace PayloadChannel diff --git a/worker/src/RTC/ActiveSpeakerObserver.cpp b/worker/src/RTC/ActiveSpeakerObserver.cpp index e86bdfcdb1..7375c7be9c 100644 --- a/worker/src/RTC/ActiveSpeakerObserver.cpp +++ b/worker/src/RTC/ActiveSpeakerObserver.cpp @@ -95,19 +95,15 @@ namespace RTC } ActiveSpeakerObserver::ActiveSpeakerObserver( - RTC::Shared* shared, const std::string& id, RTC::RtpObserver::Listener* listener, json& data) + RTC::Shared* shared, + const std::string& id, + RTC::RtpObserver::Listener* listener, + const FBS::ActiveSpeakerObserver::ActiveSpeakerObserverOptions* options) : RTC::RtpObserver(shared, id, listener) { MS_TRACE(); - auto jsonIntervalIt = data.find("interval"); - - if (jsonIntervalIt == data.end() || !jsonIntervalIt->is_number()) - { - MS_THROW_TYPE_ERROR("missing interval"); - } - - this->interval = jsonIntervalIt->get(); + this->interval = options->interval(); if (this->interval < 100) this->interval = 100; @@ -122,8 +118,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelNotificationHandler*/ nullptr); } ActiveSpeakerObserver::~ActiveSpeakerObserver() @@ -275,10 +270,14 @@ namespace RTC if (!this->mapProducerSpeakers.empty() && CalculateActiveSpeaker()) { - json data = json::object(); - data["producerId"] = this->dominantId; - - this->shared->channelNotifier->Emit(this->id, "dominantspeaker", data); + auto notification = FBS::ActiveSpeakerObserver::CreateDominantSpeakerNotificationDirect( + this->shared->channelNotifier->GetBufferBuilder(), this->dominantId.c_str()); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::ACTIVESPEAKEROBSERVER_DOMINANT_SPEAKER, + FBS::Notification::Body::FBS_ActiveSpeakerObserver_DominantSpeakerNotification, + notification); } } @@ -324,7 +323,7 @@ namespace RTC { auto* producerSpeaker = kv.second; auto* speaker = producerSpeaker->speaker; - auto& id = producerSpeaker->producer->id; + const auto& id = producerSpeaker->producer->id; if (id == this->dominantId || speaker->paused) { @@ -370,7 +369,7 @@ namespace RTC { auto* producerSpeaker = kv.second; auto* speaker = producerSpeaker->speaker; - auto& id = producerSpeaker->producer->id; + const auto& id = producerSpeaker->producer->id; uint64_t idle = now - speaker->lastLevelChangeTime; if (SpeakerIdleTimeout < idle && (this->dominantId.empty() || id != this->dominantId)) diff --git a/worker/src/RTC/AudioLevelObserver.cpp b/worker/src/RTC/AudioLevelObserver.cpp index 4339e49d16..1de513774e 100644 --- a/worker/src/RTC/AudioLevelObserver.cpp +++ b/worker/src/RTC/AudioLevelObserver.cpp @@ -14,45 +14,21 @@ namespace RTC /* Instance methods. */ AudioLevelObserver::AudioLevelObserver( - RTC::Shared* shared, const std::string& id, RTC::RtpObserver::Listener* listener, json& data) + RTC::Shared* shared, + const std::string& id, + RTC::RtpObserver::Listener* listener, + const FBS::AudioLevelObserver::AudioLevelObserverOptions* options) : RTC::RtpObserver(shared, id, listener) { MS_TRACE(); - auto jsonMaxEntriesIt = data.find("maxEntries"); + this->maxEntries = options->maxEntries(); + this->threshold = options->threshold(); + this->interval = options->interval(); - // clang-format off - if ( - jsonMaxEntriesIt == data.end() || - !Utils::Json::IsPositiveInteger(*jsonMaxEntriesIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing maxEntries"); - } - - this->maxEntries = jsonMaxEntriesIt->get(); - - if (this->maxEntries < 1) - MS_THROW_TYPE_ERROR("invalid maxEntries value %" PRIu16, this->maxEntries); - - auto jsonThresholdIt = data.find("threshold"); - - if (jsonThresholdIt == data.end() || !jsonThresholdIt->is_number()) - MS_THROW_TYPE_ERROR("missing threshold"); - - this->threshold = jsonThresholdIt->get(); - - if (this->threshold < -127 || this->threshold > 0) + if (this->threshold > 0) MS_THROW_TYPE_ERROR("invalid threshold value %" PRIi8, this->threshold); - auto jsonIntervalIt = data.find("interval"); - - if (jsonIntervalIt == data.end() || !jsonIntervalIt->is_number()) - MS_THROW_TYPE_ERROR("missing interval"); - - this->interval = jsonIntervalIt->get(); - if (this->interval < 250) this->interval = 250; else if (this->interval > 5000) @@ -66,8 +42,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelNotificationHandler*/ nullptr); } AudioLevelObserver::~AudioLevelObserver() @@ -141,7 +116,8 @@ namespace RTC { this->silence = true; - this->shared->channelNotifier->Emit(this->id, "silence"); + this->shared->channelNotifier->Emit( + this->id, FBS::Notification::Event::AUDIOLEVELOBSERVER_SILENCE); } } @@ -184,25 +160,31 @@ namespace RTC this->silence = false; uint16_t idx{ 0 }; - auto rit = mapDBovsProducer.crbegin(); - json data = json::array(); + auto rit = mapDBovsProducer.crbegin(); + + std::vector> volumes; for (; idx < this->maxEntries && rit != mapDBovsProducer.crend(); ++idx, ++rit) { - data.emplace_back(json::value_t::object); - - auto& jsonEntry = data[idx]; - - jsonEntry["producerId"] = rit->second->id; - jsonEntry["volume"] = rit->first; + volumes.emplace_back(FBS::AudioLevelObserver::CreateVolumeDirect( + this->shared->channelNotifier->GetBufferBuilder(), rit->second->id.c_str(), rit->first)); } - this->shared->channelNotifier->Emit(this->id, "volumes", data); + auto notification = FBS::AudioLevelObserver::CreateVolumesNotificationDirect( + this->shared->channelNotifier->GetBufferBuilder(), &volumes); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::AUDIOLEVELOBSERVER_VOLUMES, + FBS::Notification::Body::FBS_AudioLevelObserver_VolumesNotification, + notification); } else if (!this->silence) { this->silence = true; - this->shared->channelNotifier->Emit(this->id, "silence"); + + this->shared->channelNotifier->Emit( + this->id, FBS::Notification::Event::AUDIOLEVELOBSERVER_SILENCE); } } diff --git a/worker/src/RTC/Consumer.cpp b/worker/src/RTC/Consumer.cpp index 0d1cc9dd9a..97d56b0cc1 100644 --- a/worker/src/RTC/Consumer.cpp +++ b/worker/src/RTC/Consumer.cpp @@ -17,30 +17,16 @@ namespace RTC const std::string& id, const std::string& producerId, Listener* listener, - json& data, + const FBS::Transport::ConsumeRequest* data, RTC::RtpParameters::Type type) : id(id), producerId(producerId), shared(shared), listener(listener), type(type) { MS_TRACE(); - auto jsonKindIt = data.find("kind"); - - if (jsonKindIt == data.end() || !jsonKindIt->is_string()) - MS_THROW_TYPE_ERROR("missing kind"); - - // This may throw. - this->kind = RTC::Media::GetKind(jsonKindIt->get()); - - if (this->kind == RTC::Media::Kind::ALL) - MS_THROW_TYPE_ERROR("invalid empty kind"); - - auto jsonRtpParametersIt = data.find("rtpParameters"); - - if (jsonRtpParametersIt == data.end() || !jsonRtpParametersIt->is_object()) - MS_THROW_TYPE_ERROR("missing rtpParameters"); + this->kind = RTC::Media::Kind(data->kind()); // This may throw. - this->rtpParameters = RTC::RtpParameters(*jsonRtpParametersIt); + this->rtpParameters = RTC::RtpParameters(data->rtpParameters()); if (this->rtpParameters.encodings.empty()) MS_THROW_TYPE_ERROR("empty rtpParameters.encodings"); @@ -54,19 +40,14 @@ namespace RTC MS_THROW_TYPE_ERROR("invalid encoding in rtpParameters (missing rtx.ssrc)"); } - auto jsonConsumableRtpEncodingsIt = data.find("consumableRtpEncodings"); - - if (jsonConsumableRtpEncodingsIt == data.end() || !jsonConsumableRtpEncodingsIt->is_array()) - MS_THROW_TYPE_ERROR("missing consumableRtpEncodings"); - - if (jsonConsumableRtpEncodingsIt->empty()) + if (data->consumableRtpEncodings()->size() == 0) MS_THROW_TYPE_ERROR("empty consumableRtpEncodings"); - this->consumableRtpEncodings.reserve(jsonConsumableRtpEncodingsIt->size()); + this->consumableRtpEncodings.reserve(data->consumableRtpEncodings()->size()); - for (size_t i{ 0 }; i < jsonConsumableRtpEncodingsIt->size(); ++i) + for (size_t i{ 0 }; i < data->consumableRtpEncodings()->size(); ++i) { - auto& entry = (*jsonConsumableRtpEncodingsIt)[i]; + const auto* entry = data->consumableRtpEncodings()->Get(i); // This may throw due the constructor of RTC::RtpEncodingParameters. this->consumableRtpEncodings.emplace_back(entry); @@ -121,10 +102,8 @@ namespace RTC } } - auto jsonPausedIt = data.find("paused"); - - if (jsonPausedIt != data.end() && jsonPausedIt->is_boolean()) - this->paused = jsonPausedIt->get(); + // paused is set to false by default. + this->paused = data->paused(); // Fill supported codec payload types. for (auto& codec : this->rtpParameters.codecs) @@ -158,113 +137,77 @@ namespace RTC MS_TRACE(); } - void Consumer::FillJson(json& jsonObject) const + flatbuffers::Offset Consumer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add id. - jsonObject["id"] = this->id; - - // Add producerId. - jsonObject["producerId"] = this->producerId; - - // Add kind. - jsonObject["kind"] = RTC::Media::GetString(this->kind); - // Add rtpParameters. - this->rtpParameters.FillJson(jsonObject["rtpParameters"]); - - // Add type. - jsonObject["type"] = RTC::RtpParameters::GetTypeString(this->type); + auto rtpParameters = this->rtpParameters.FillBuffer(builder); // Add consumableRtpEncodings. - jsonObject["consumableRtpEncodings"] = json::array(); - auto jsonConsumableRtpEncodingsIt = jsonObject.find("consumableRtpEncodings"); + std::vector> consumableRtpEncodings; + consumableRtpEncodings.reserve(this->consumableRtpEncodings.size()); - for (size_t i{ 0 }; i < this->consumableRtpEncodings.size(); ++i) + for (const auto& encoding : this->consumableRtpEncodings) { - jsonConsumableRtpEncodingsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonConsumableRtpEncodingsIt)[i]; - const auto& encoding = this->consumableRtpEncodings[i]; - - encoding.FillJson(jsonEntry); + consumableRtpEncodings.emplace_back(encoding.FillBuffer(builder)); } // Add supportedCodecPayloadTypes. - jsonObject["supportedCodecPayloadTypes"] = json::array(); + std::vector supportedCodecPayloadTypes; for (auto i = 0; i < 128; ++i) { if (this->supportedCodecPayloadTypes[i]) - jsonObject["supportedCodecPayloadTypes"].push_back(i); + supportedCodecPayloadTypes.push_back(i); } - // Add paused. - jsonObject["paused"] = this->paused; - - // Add producerPaused. - jsonObject["producerPaused"] = this->producerPaused; - - // Add priority. - jsonObject["priority"] = this->priority; - // Add traceEventTypes. - std::vector traceEventTypes; - std::ostringstream traceEventTypesStream; + std::vector> traceEventTypes; if (this->traceEventTypes.rtp) - traceEventTypes.emplace_back("rtp"); + traceEventTypes.emplace_back(builder.CreateString("rtp")); if (this->traceEventTypes.keyframe) - traceEventTypes.emplace_back("keyframe"); + traceEventTypes.emplace_back(builder.CreateString("keyframe")); if (this->traceEventTypes.nack) - traceEventTypes.emplace_back("nack"); + traceEventTypes.emplace_back(builder.CreateString("nack")); if (this->traceEventTypes.pli) - traceEventTypes.emplace_back("pli"); + traceEventTypes.emplace_back(builder.CreateString("pli")); if (this->traceEventTypes.fir) - traceEventTypes.emplace_back("fir"); - - if (!traceEventTypes.empty()) - { - std::copy( - traceEventTypes.begin(), - traceEventTypes.end() - 1, - std::ostream_iterator(traceEventTypesStream, ",")); - traceEventTypesStream << traceEventTypes.back(); - } - - jsonObject["traceEventTypes"] = traceEventTypesStream.str(); + traceEventTypes.emplace_back(builder.CreateString("fir")); + + return FBS::Consumer::CreateBaseConsumerDumpDirect( + builder, + this->id.c_str(), + this->producerId.c_str(), + this->kind == RTC::Media::Kind::AUDIO ? FBS::RtpParameters::MediaKind::AUDIO + : FBS::RtpParameters::MediaKind::VIDEO, + rtpParameters, + &consumableRtpEncodings, + &supportedCodecPayloadTypes, + &traceEventTypes, + this->paused, + this->producerPaused, + this->priority); } void Consumer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::CONSUMER_DUMP: + case Channel::ChannelRequest::Method::CONSUMER_GET_STATS: { - json data = json::object(); - - FillJson(data); + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_Consumer_GetStatsResponse, responseOffset); break; } - case Channel::ChannelRequest::MethodId::CONSUMER_GET_STATS: - { - json data = json::array(); - - FillJsonStats(data); - - request->Accept(data); - - break; - } - - case Channel::ChannelRequest::MethodId::CONSUMER_PAUSE: + case Channel::ChannelRequest::Method::CONSUMER_PAUSE: { if (this->paused) { @@ -287,7 +230,7 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::CONSUMER_RESUME: + case Channel::ChannelRequest::Method::CONSUMER_RESUME: { if (!this->paused) { @@ -308,46 +251,33 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::CONSUMER_SET_PRIORITY: + case Channel::ChannelRequest::Method::CONSUMER_SET_PRIORITY: { - auto jsonPriorityIt = request->data.find("priority"); + const auto* body = request->data->body_as(); - if (jsonPriorityIt == request->data.end() || !jsonPriorityIt->is_number()) - MS_THROW_TYPE_ERROR("wrong priority (not a number)"); - - auto priority = jsonPriorityIt->get(); - - if (priority < 1u) + if (body->priority() < 1u) MS_THROW_TYPE_ERROR("wrong priority (must be higher than 0)"); - this->priority = priority; - - json data = json::object(); + this->priority = body->priority(); - data["priority"] = this->priority; + auto responseOffset = + FBS::Consumer::CreateSetPriorityResponse(request->GetBufferBuilder(), this->priority); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_Consumer_SetPriorityResponse, responseOffset); break; } - case Channel::ChannelRequest::MethodId::CONSUMER_ENABLE_TRACE_EVENT: + case Channel::ChannelRequest::Method::CONSUMER_ENABLE_TRACE_EVENT: { - auto jsonTypesIt = request->data.find("types"); - - // Disable all if no entries. - if (jsonTypesIt == request->data.end() || !jsonTypesIt->is_array()) - MS_THROW_TYPE_ERROR("wrong types (not an array)"); + const auto* body = request->data->body_as(); // Reset traceEventTypes. struct TraceEventTypes newTraceEventTypes; - for (const auto& type : *jsonTypesIt) + for (const auto& type : *body->events()) { - if (!type.is_string()) - MS_THROW_TYPE_ERROR("wrong type (not a string)"); - - const std::string typeStr = type.get(); + const auto typeStr = type->str(); if (typeStr == "rtp") newTraceEventTypes.rtp = true; @@ -370,7 +300,7 @@ namespace RTC default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } } @@ -419,7 +349,7 @@ namespace RTC if (wasActive) UserOnPaused(); - this->shared->channelNotifier->Emit(this->id, "producerpause"); + this->shared->channelNotifier->Emit(this->id, FBS::Notification::Event::CONSUMER_PRODUCER_PAUSE); } void Consumer::ProducerResumed() @@ -436,7 +366,7 @@ namespace RTC if (IsActive()) UserOnResumed(); - this->shared->channelNotifier->Emit(this->id, "producerresume"); + this->shared->channelNotifier->Emit(this->id, FBS::Notification::Event::CONSUMER_PRODUCER_RESUME); } void Consumer::ProducerRtpStreamScores(const std::vector* scores) @@ -457,7 +387,7 @@ namespace RTC MS_DEBUG_DEV("Producer closed [consumerId:%s]", this->id.c_str()); - this->shared->channelNotifier->Emit(this->id, "producerclose"); + this->shared->channelNotifier->Emit(this->id, FBS::Notification::Event::CONSUMER_PRODUCER_CLOSE); this->listener->OnConsumerProducerClosed(this); } @@ -468,33 +398,33 @@ namespace RTC if (this->traceEventTypes.keyframe && packet->IsKeyFrame()) { - json data = json::object(); - - data["type"] = "keyframe"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "out"; - - packet->FillJson(data["info"]); - - if (isRtx) - data["info"]["isRtx"] = true; - - this->shared->channelNotifier->Emit(this->id, "trace", data); + auto traceInfo = FBS::Consumer::CreateKeyFrameTraceInfo( + this->shared->channelNotifier->GetBufferBuilder(), isRtx); + + auto notification = FBS::Consumer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Consumer::TraceType::KEYFRAME, + DepLibUV::GetTimeMs(), + FBS::Consumer::TraceDirection::DIRECTION_OUT, + FBS::Consumer::TraceInfo::KeyFrameTraceInfo, + traceInfo.Union()); + + EmitTraceEvent(notification); } else if (this->traceEventTypes.rtp) { - json data = json::object(); - - data["type"] = "rtp"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "out"; - - packet->FillJson(data["info"]); - - if (isRtx) - data["info"]["isRtx"] = true; - - this->shared->channelNotifier->Emit(this->id, "trace", data); + auto traceInfo = + FBS::Consumer::CreateRtpTraceInfo(this->shared->channelNotifier->GetBufferBuilder(), isRtx); + + auto notification = FBS::Consumer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Consumer::TraceType::RTP, + DepLibUV::GetTimeMs(), + FBS::Consumer::TraceDirection::DIRECTION_OUT, + FBS::Consumer::TraceInfo::RtpTraceInfo, + traceInfo.Union()); + + EmitTraceEvent(notification); } } @@ -505,14 +435,18 @@ namespace RTC if (!this->traceEventTypes.pli) return; - json data = json::object(); + auto traceInfo = + FBS::Consumer::CreatePliTraceInfo(this->shared->channelNotifier->GetBufferBuilder(), ssrc); - data["type"] = "pli"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "in"; - data["info"]["ssrc"] = ssrc; + auto notification = FBS::Consumer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Consumer::TraceType::PLI, + DepLibUV::GetTimeMs(), + FBS::Consumer::TraceDirection::DIRECTION_IN, + FBS::Consumer::TraceInfo::PliTraceInfo, + traceInfo.Union()); - this->shared->channelNotifier->Emit(this->id, "trace", data); + EmitTraceEvent(notification); } void Consumer::EmitTraceEventFirType(uint32_t ssrc) const @@ -522,14 +456,18 @@ namespace RTC if (!this->traceEventTypes.fir) return; - json data = json::object(); + auto traceInfo = + FBS::Consumer::CreateFirTraceInfo(this->shared->channelNotifier->GetBufferBuilder(), ssrc); - data["type"] = "fir"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "in"; - data["info"]["ssrc"] = ssrc; + auto notification = FBS::Consumer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Consumer::TraceType::FIR, + DepLibUV::GetTimeMs(), + FBS::Consumer::TraceDirection::DIRECTION_IN, + FBS::Consumer::TraceInfo::FirTraceInfo, + traceInfo.Union()); - this->shared->channelNotifier->Emit(this->id, "trace", data); + EmitTraceEvent(notification); } void Consumer::EmitTraceEventNackType() const @@ -539,13 +477,23 @@ namespace RTC if (!this->traceEventTypes.nack) return; - json data = json::object(); + auto notification = FBS::Consumer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Consumer::TraceType::NACK, + DepLibUV::GetTimeMs(), + FBS::Consumer::TraceDirection::DIRECTION_IN); + + EmitTraceEvent(notification); + } - data["type"] = "nack"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "in"; - data["info"] = json::object(); + void Consumer::EmitTraceEvent(flatbuffers::Offset& notification) const + { + MS_TRACE(); - this->shared->channelNotifier->Emit(this->id, "trace", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::CONSUMER_TRACE, + FBS::Notification::Body::FBS_Consumer_TraceNotification, + notification); } } // namespace RTC diff --git a/worker/src/RTC/DataConsumer.cpp b/worker/src/RTC/DataConsumer.cpp index 9add8cab3b..c3a0bdf9b1 100644 --- a/worker/src/RTC/DataConsumer.cpp +++ b/worker/src/RTC/DataConsumer.cpp @@ -19,22 +19,14 @@ namespace RTC const std::string& dataProducerId, RTC::SctpAssociation* sctpAssociation, RTC::DataConsumer::Listener* listener, - json& data, + const FBS::Transport::ConsumeDataRequest* data, size_t maxMessageSize) : id(id), dataProducerId(dataProducerId), shared(shared), sctpAssociation(sctpAssociation), listener(listener), maxMessageSize(maxMessageSize) { MS_TRACE(); - auto jsonTypeIt = data.find("type"); - auto jsonSctpStreamParametersIt = data.find("sctpStreamParameters"); - auto jsonLabelIt = data.find("label"); - auto jsonProtocolIt = data.find("protocol"); - - if (jsonTypeIt == data.end() || !jsonTypeIt->is_string()) - MS_THROW_TYPE_ERROR("missing type"); - - this->typeString = jsonTypeIt->get(); + this->typeString = data->type()->str(); if (this->typeString == "sctp") this->type = DataConsumer::Type::SCTP; @@ -45,32 +37,27 @@ namespace RTC if (this->type == DataConsumer::Type::SCTP) { - // clang-format off - if ( - jsonSctpStreamParametersIt == data.end() || - !jsonSctpStreamParametersIt->is_object() - ) - // clang-format on + if (!flatbuffers::IsFieldPresent( + data, FBS::Transport::ConsumeDataRequest::VT_SCTPSTREAMPARAMETERS)) { MS_THROW_TYPE_ERROR("missing sctpStreamParameters"); } // This may throw. - this->sctpStreamParameters = RTC::SctpStreamParameters(*jsonSctpStreamParametersIt); + this->sctpStreamParameters = RTC::SctpStreamParameters(data->sctpStreamParameters()); } - if (jsonLabelIt != data.end() && jsonLabelIt->is_string()) - this->label = jsonLabelIt->get(); + if (flatbuffers::IsFieldPresent(data, FBS::Transport::ConsumeDataRequest::VT_LABEL)) + this->label = data->label()->str(); - if (jsonProtocolIt != data.end() && jsonProtocolIt->is_string()) - this->protocol = jsonProtocolIt->get(); + if (flatbuffers::IsFieldPresent(data, FBS::Transport::ConsumeDataRequest::VT_PROTOCOL)) + this->protocol = data->protocol()->str(); // NOTE: This may throw. this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ this, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelNotificationHandler*/ nullptr); } DataConsumer::~DataConsumer() @@ -80,93 +67,75 @@ namespace RTC this->shared->channelMessageRegistrator->UnregisterHandler(this->id); } - void DataConsumer::FillJson(json& jsonObject) const + flatbuffers::Offset DataConsumer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add id. - jsonObject["id"] = this->id; - - // Add type. - jsonObject["type"] = this->typeString; - - // Add dataProducerId. - jsonObject["dataProducerId"] = this->dataProducerId; + flatbuffers::Offset sctpStreamParametersOffset; // Add sctpStreamParameters. if (this->type == DataConsumer::Type::SCTP) { - this->sctpStreamParameters.FillJson(jsonObject["sctpStreamParameters"]); + sctpStreamParametersOffset = this->sctpStreamParameters.FillBuffer(builder); } - // Add label. - jsonObject["label"] = this->label; - - // Add protocol. - jsonObject["protocol"] = this->protocol; - - // Add bufferedAmountLowThreshold. - jsonObject["bufferedAmountLowThreshold"] = this->bufferedAmountLowThreshold; + return FBS::DataConsumer::CreateDumpResponseDirect( + builder, + this->id.c_str(), + this->dataProducerId.c_str(), + this->typeString.c_str(), + sctpStreamParametersOffset, + this->label.c_str(), + this->protocol.c_str()); } - void DataConsumer::FillJsonStats(json& jsonArray) const + flatbuffers::Offset DataConsumer::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - jsonArray.emplace_back(json::value_t::object); - auto& jsonObject = jsonArray[0]; - - // Add type. - jsonObject["type"] = "data-consumer"; - - // Add timestamp. - jsonObject["timestamp"] = DepLibUV::GetTimeMs(); - - // Add label. - jsonObject["label"] = this->label; - - // Add protocol. - jsonObject["protocol"] = this->protocol; - - // Add messagesSent. - jsonObject["messagesSent"] = this->messagesSent; - - // Add bytesSent. - jsonObject["bytesSent"] = this->bytesSent; - - // Add bufferedAmount. - jsonObject["bufferedAmount"] = this->bufferedAmount; + return FBS::DataConsumer::CreateGetStatsResponseDirect( + builder, + // timestamp. + DepLibUV::GetTimeMs(), + // label. + this->label.c_str(), + // protocol. + this->protocol.c_str(), + // messagesSent. + this->messagesSent, + // bytesSent. + this->bytesSent, + // bufferedAmount. + this->bufferedAmount); } void DataConsumer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::DATA_CONSUMER_DUMP: + case Channel::ChannelRequest::Method::DATA_CONSUMER_DUMP: { - json data = json::object(); - - FillJson(data); + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_DataConsumer_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::DATA_CONSUMER_GET_STATS: + case Channel::ChannelRequest::Method::DATA_CONSUMER_GET_STATS: { - json data = json::array(); - - FillJsonStats(data); + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_DataConsumer_GetStatsResponse, responseOffset); break; } - case Channel::ChannelRequest::MethodId::DATA_CONSUMER_GET_BUFFERED_AMOUNT: + case Channel::ChannelRequest::Method::DATA_CONSUMER_GET_BUFFERED_AMOUNT: { if (this->GetType() != RTC::DataConsumer::Type::SCTP) { @@ -179,28 +148,26 @@ namespace RTC } // Create status response. - json data = json::object(); + auto responseOffset = FBS::DataConsumer::CreateGetBufferedAmountResponse( + request->GetBufferBuilder(), this->sctpAssociation->GetSctpBufferedAmount()); - data["bufferedAmount"] = this->sctpAssociation->GetSctpBufferedAmount(); - - request->Accept(data); + request->Accept( + FBS::Response::Body::FBS_DataConsumer_GetBufferedAmountResponse, responseOffset); break; } - case Channel::ChannelRequest::MethodId::DATA_CONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD: + case Channel::ChannelRequest::Method::DATA_CONSUMER_SET_BUFFERED_AMOUNT_LOW_THRESHOLD: { if (this->GetType() != DataConsumer::Type::SCTP) { MS_THROW_TYPE_ERROR("invalid DataConsumer type"); } - auto jsonThresholdIt = request->data.find("threshold"); - - if (jsonThresholdIt == request->data.end() || !jsonThresholdIt->is_number_unsigned()) - MS_THROW_TYPE_ERROR("wrong bufferedAmountThreshold (not an unsigned number)"); + const auto* body = + request->data->body_as(); - this->bufferedAmountLowThreshold = jsonThresholdIt->get(); + this->bufferedAmountLowThreshold = body->threshold(); request->Accept(); @@ -223,20 +190,7 @@ namespace RTC break; } - default: - { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); - } - } - } - - void DataConsumer::HandleRequest(PayloadChannel::PayloadChannelRequest* request) - { - MS_TRACE(); - - switch (request->methodId) - { - case PayloadChannel::PayloadChannelRequest::MethodId::DATA_CONSUMER_SEND: + case Channel::ChannelRequest::Method::DATA_CONSUMER_SEND: { if (this->GetType() != RTC::DataConsumer::Type::SCTP) { @@ -248,29 +202,29 @@ namespace RTC MS_THROW_ERROR("no SCTP association present"); } - int ppid; + const auto* body = request->data->body_as(); + const uint8_t* data{ nullptr }; + size_t len{ 0 }; - // This may throw. - // NOTE: If this throws we have to catch the error and throw a MediaSoupError - // intead, otherwise the process would crash. - try + if (body->data_type() == FBS::DataConsumer::Data::String) { - ppid = std::stoi(request->data); + data = body->data_as_String()->value()->Data(); + len = body->data_as_String()->value()->size(); } - catch (const std::exception& error) + else { - MS_THROW_TYPE_ERROR("invalid PPID value: %s", error.what()); + data = body->data_as_Binary()->value()->Data(); + len = body->data_as_Binary()->value()->size(); } - const auto* msg = request->payload; - auto len = request->payloadLen; + const int ppid = body->ppid(); if (len > this->maxMessageSize) { MS_THROW_TYPE_ERROR( "given message exceeds maxMessageSize value [maxMessageSize:%zu, len:%zu]", - len, - this->maxMessageSize); + this->maxMessageSize, + len); } const auto* cb = new onQueuedCallback( @@ -279,18 +233,17 @@ namespace RTC if (queued) request->Accept(); else - request->Error( - sctpSendBufferFull == true ? "sctpsendbufferfull" : "message send failed"); + request->Error(sctpSendBufferFull ? "sctpsendbufferfull" : "message send failed"); }); - SendMessage(ppid, msg, len, cb); + SendMessage(ppid, data, len, cb); break; } default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } } @@ -349,12 +302,14 @@ namespace RTC this->forceTriggerBufferedAmountLow = false; // Notify the Node DataConsumer. - std::string data(R"({"bufferedAmount":)"); - - data.append(std::to_string(this->bufferedAmount)); - data.append("}"); - - this->shared->channelNotifier->Emit(this->id, "bufferedamountlow", data); + auto bufferedAmountLowOffset = FBS::DataConsumer::CreateBufferedAmountLowNotification( + this->shared->channelNotifier->GetBufferBuilder(), this->bufferedAmount); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::DATACONSUMER_BUFFERED_AMOUNT_LOW, + FBS::Notification::Body::FBS_DataConsumer_BufferedAmountLowNotification, + bufferedAmountLowOffset); } } @@ -362,7 +317,8 @@ namespace RTC { MS_TRACE(); - this->shared->channelNotifier->Emit(this->id, "sctpsendbufferfull"); + this->shared->channelNotifier->Emit( + this->id, FBS::Notification::Event::DATACONSUMER_SCTP_SENDBUFFER_FULL); } // The caller (Router) is supposed to proceed with the deletion of this DataConsumer @@ -375,7 +331,8 @@ namespace RTC MS_DEBUG_DEV("DataProducer closed [dataConsumerId:%s]", this->id.c_str()); - this->shared->channelNotifier->Emit(this->id, "dataproducerclose"); + this->shared->channelNotifier->Emit( + this->id, FBS::Notification::Event::DATACONSUMER_DATAPRODUCER_CLOSE); this->listener->OnDataConsumerDataProducerClosed(this); } diff --git a/worker/src/RTC/DataProducer.cpp b/worker/src/RTC/DataProducer.cpp index f0888c83ae..3fffe1cc6e 100644 --- a/worker/src/RTC/DataProducer.cpp +++ b/worker/src/RTC/DataProducer.cpp @@ -17,20 +17,12 @@ namespace RTC const std::string& id, size_t maxMessageSize, RTC::DataProducer::Listener* listener, - json& data) + const FBS::Transport::ProduceDataRequest* data) : id(id), shared(shared), maxMessageSize(maxMessageSize), listener(listener) { MS_TRACE(); - auto jsonTypeIt = data.find("type"); - auto jsonSctpStreamParametersIt = data.find("sctpStreamParameters"); - auto jsonLabelIt = data.find("label"); - auto jsonProtocolIt = data.find("protocol"); - - if (jsonTypeIt == data.end() || !jsonTypeIt->is_string()) - MS_THROW_TYPE_ERROR("missing type"); - - this->typeString = jsonTypeIt->get(); + this->typeString = data->type()->str(); if (this->typeString == "sctp") this->type = DataProducer::Type::SCTP; @@ -41,32 +33,27 @@ namespace RTC if (this->type == DataProducer::Type::SCTP) { - // clang-format off - if ( - jsonSctpStreamParametersIt == data.end() || - !jsonSctpStreamParametersIt->is_object() - ) - // clang-format on + if (!flatbuffers::IsFieldPresent( + data, FBS::Transport::ProduceDataRequest::VT_SCTPSTREAMPARAMETERS)) { MS_THROW_TYPE_ERROR("missing sctpStreamParameters"); } // This may throw. - this->sctpStreamParameters = RTC::SctpStreamParameters(*jsonSctpStreamParametersIt); + this->sctpStreamParameters = RTC::SctpStreamParameters(data->sctpStreamParameters()); } - if (jsonLabelIt != data.end() && jsonLabelIt->is_string()) - this->label = jsonLabelIt->get(); + if (flatbuffers::IsFieldPresent(data, FBS::Transport::ProduceDataRequest::VT_LABEL)) + this->label = data->label()->str(); - if (jsonProtocolIt != data.end() && jsonProtocolIt->is_string()) - this->protocol = jsonProtocolIt->get(); + if (flatbuffers::IsFieldPresent(data, FBS::Transport::ProduceDataRequest::VT_PROTOCOL)) + this->protocol = data->protocol()->str(); // NOTE: This may throw. this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ this); + /*channelNotificationHandler*/ this); } DataProducer::~DataProducer() @@ -76,124 +63,110 @@ namespace RTC this->shared->channelMessageRegistrator->UnregisterHandler(this->id); } - void DataProducer::FillJson(json& jsonObject) const + flatbuffers::Offset DataProducer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add id. - jsonObject["id"] = this->id; - - // Add type. - jsonObject["type"] = this->typeString; + flatbuffers::Offset sctpStreamParametersOffset; // Add sctpStreamParameters. if (this->type == DataProducer::Type::SCTP) { - this->sctpStreamParameters.FillJson(jsonObject["sctpStreamParameters"]); + sctpStreamParametersOffset = this->sctpStreamParameters.FillBuffer(builder); } - // Add label. - jsonObject["label"] = this->label; - - // Add protocol. - jsonObject["protocol"] = this->protocol; + return FBS::DataProducer::CreateDumpResponseDirect( + builder, + this->id.c_str(), + this->typeString.c_str(), + sctpStreamParametersOffset, + this->label.c_str(), + this->protocol.c_str()); } - void DataProducer::FillJsonStats(json& jsonArray) const + flatbuffers::Offset DataProducer::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - jsonArray.emplace_back(json::value_t::object); - auto& jsonObject = jsonArray[0]; - - // Add type. - jsonObject["type"] = "data-producer"; - - // Add timestamp. - jsonObject["timestamp"] = DepLibUV::GetTimeMs(); - - // Add label. - jsonObject["label"] = this->label; - - // Add protocol. - jsonObject["protocol"] = this->protocol; - - // Add messagesReceived. - jsonObject["messagesReceived"] = this->messagesReceived; - - // Add bytesReceived. - jsonObject["bytesReceived"] = this->bytesReceived; + return FBS::DataProducer::CreateGetStatsResponseDirect( + builder, + // timestamp. + DepLibUV::GetTimeMs(), + // label. + this->label.c_str(), + // protocol. + this->protocol.c_str(), + // messagesReceived. + this->messagesReceived, + // bytesReceived. + this->bytesReceived); } void DataProducer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::DATA_PRODUCER_DUMP: + case Channel::ChannelRequest::Method::DATA_PRODUCER_DUMP: { - json data = json::object(); + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); - FillJson(data); - - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_DataProducer_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::DATA_PRODUCER_GET_STATS: + case Channel::ChannelRequest::Method::DATA_PRODUCER_GET_STATS: { - json data = json::array(); - - FillJsonStats(data); + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_DataProducer_GetStatsResponse, responseOffset); break; } default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } } - void DataProducer::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) + void DataProducer::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); - switch (notification->eventId) + switch (notification->event) { - case PayloadChannel::PayloadChannelNotification::EventId::DATA_PRODUCER_SEND: + case Channel::ChannelNotification::Event::DATA_PRODUCER_SEND: { - int ppid; + const auto* body = notification->data->body_as(); + const uint8_t* data{ nullptr }; + size_t len{ 0 }; - // This may throw. - // NOTE: If this throws we have to catch the error and throw a MediaSoupError - // intead, otherwise the process would crash. - try + if (body->data_type() == FBS::DataProducer::Data::String) { - ppid = std::stoi(notification->data); + data = body->data_as_String()->value()->Data(); + len = body->data_as_String()->value()->size(); } - catch (const std::exception& error) + else { - MS_THROW_TYPE_ERROR("invalid PPID value: %s", error.what()); + data = body->data_as_Binary()->value()->Data(); + len = body->data_as_Binary()->value()->size(); } - const auto* msg = notification->payload; - auto len = notification->payloadLen; - if (len > this->maxMessageSize) { MS_THROW_TYPE_ERROR( "given message exceeds maxMessageSize value [maxMessageSize:%zu, len:%zu]", - len, - this->maxMessageSize); + this->maxMessageSize, + len); } - this->ReceiveMessage(ppid, msg, len); + this->ReceiveMessage(body->ppid(), data, len); // Increase receive transmission. this->listener->OnDataProducerReceiveData(this, len); @@ -203,7 +176,7 @@ namespace RTC default: { - MS_ERROR("unknown event '%s'", notification->event.c_str()); + MS_ERROR("unknown event '%s'", notification->eventCStr); } } } diff --git a/worker/src/RTC/DirectTransport.cpp b/worker/src/RTC/DirectTransport.cpp index fe28591730..f4822d74e2 100644 --- a/worker/src/RTC/DirectTransport.cpp +++ b/worker/src/RTC/DirectTransport.cpp @@ -11,8 +11,11 @@ namespace RTC // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) DirectTransport::DirectTransport( - RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data) - : RTC::Transport::Transport(shared, id, listener, data) + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::DirectTransport::DirectTransportOptions* options) + : RTC::Transport::Transport(shared, id, listener, options->base()) { MS_TRACE(); @@ -20,8 +23,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ this, - /*payloadChannelNotificationHandler*/ this); + /*channelNotificationHandler*/ this); } DirectTransport::~DirectTransport() @@ -31,57 +33,80 @@ namespace RTC this->shared->channelMessageRegistrator->UnregisterHandler(this->id); } - void DirectTransport::FillJson(json& jsonObject) const + flatbuffers::Offset DirectTransport::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { - MS_TRACE(); + // Add base transport dump. + auto base = Transport::FillBuffer(builder); - // Call the parent method. - RTC::Transport::FillJson(jsonObject); + return FBS::DirectTransport::CreateDumpResponse(builder, base); } - void DirectTransport::FillJsonStats(json& jsonArray) + flatbuffers::Offset DirectTransport::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); - // Call the parent method. - RTC::Transport::FillJsonStats(jsonArray); - - auto& jsonObject = jsonArray[0]; + // Base Transport stats. + auto base = Transport::FillBufferStats(builder); - // Add type. - jsonObject["type"] = "direct-transport"; + return FBS::DirectTransport::CreateGetStatsResponse(builder, base); } void DirectTransport::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - // Pass it to the parent class. - RTC::Transport::HandleRequest(request); + switch (request->method) + { + case Channel::ChannelRequest::Method::TRANSPORT_GET_STATS: + { + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::FBS_DirectTransport_GetStatsResponse, responseOffset); + + break; + } + + case Channel::ChannelRequest::Method::TRANSPORT_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::FBS_PipeTransport_DumpResponse, dumpOffset); + + break; + } + + default: + { + // Pass it to the parent class. + RTC::Transport::HandleRequest(request); + } + } } - void DirectTransport::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) + void DirectTransport::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); - switch (notification->eventId) + switch (notification->event) { - case PayloadChannel::PayloadChannelNotification::EventId::TRANSPORT_SEND_RTCP: + case Channel::ChannelNotification::Event::TRANSPORT_SEND_RTCP: { - const auto* data = notification->payload; - auto len = notification->payloadLen; + const auto* body = notification->data->body_as(); + auto len = body->data()->size(); // Increase receive transmission. RTC::Transport::DataReceived(len); if (len > RTC::MtuSize + 100) { - MS_WARN_TAG(rtp, "given RTCP packet exceeds maximum size [len:%zu]", len); + MS_WARN_TAG(rtp, "given RTCP packet exceeds maximum size [len:%i]", len); return; } - RTC::RTCP::Packet* packet = RTC::RTCP::Packet::Parse(data, len); + RTC::RTCP::Packet* packet = RTC::RTCP::Packet::Parse(body->data()->data(), len); if (!packet) { @@ -121,11 +146,17 @@ namespace RTC return; } - const uint8_t* data = packet->GetData(); - const size_t len = packet->GetSize(); + const auto data = this->shared->channelNotifier->GetBufferBuilder().CreateVector( + packet->GetData(), packet->GetSize()); - // Notify the Node DirectTransport. - this->shared->payloadChannelNotifier->Emit(consumer->id, "rtp", data, len); + auto notification = + FBS::Consumer::CreateRtpNotification(this->shared->channelNotifier->GetBufferBuilder(), data); + + this->shared->channelNotifier->Emit( + consumer->id, + FBS::Notification::Event::CONSUMER_RTP, + FBS::Notification::Body::FBS_Consumer_RtpNotification, + notification); if (cb) { @@ -134,21 +165,28 @@ namespace RTC } // Increase send transmission. - RTC::Transport::DataSent(len); + RTC::Transport::DataSent(packet->GetSize()); } void DirectTransport::SendRtcpPacket(RTC::RTCP::Packet* packet) { MS_TRACE(); - const uint8_t* data = packet->GetData(); - const size_t len = packet->GetSize(); - // Notify the Node DirectTransport. - this->shared->payloadChannelNotifier->Emit(this->id, "rtcp", data, len); + const auto data = this->shared->channelNotifier->GetBufferBuilder().CreateVector( + packet->GetData(), packet->GetSize()); + + auto notification = FBS::DirectTransport::CreateRtcpNotification( + this->shared->channelNotifier->GetBufferBuilder(), data); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::DIRECTTRANSPORT_RTCP, + FBS::Notification::Body::FBS_DirectTransport_RtcpNotification, + notification); // Increase send transmission. - RTC::Transport::DataSent(len); + RTC::Transport::DataSent(packet->GetSize()); } void DirectTransport::SendRtcpCompoundPacket(RTC::RTCP::CompoundPacket* packet) @@ -157,14 +195,17 @@ namespace RTC packet->Serialize(RTC::RTCP::Buffer); - const uint8_t* data = packet->GetData(); - const size_t len = packet->GetSize(); + const auto data = this->shared->channelNotifier->GetBufferBuilder().CreateVector( + packet->GetData(), packet->GetSize()); - // Notify the Node DirectTransport. - this->shared->payloadChannelNotifier->Emit(this->id, "rtcp", data, len); + auto notification = FBS::DirectTransport::CreateRtcpNotification( + this->shared->channelNotifier->GetBufferBuilder(), data); - // Increase send transmission. - RTC::Transport::DataSent(len); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::DIRECTTRANSPORT_RTCP, + FBS::Notification::Body::FBS_DirectTransport_RtcpNotification, + notification); } void DirectTransport::SendMessage( @@ -173,11 +214,16 @@ namespace RTC MS_TRACE(); // Notify the Node DirectTransport. - json data = json::object(); + auto data = this->shared->channelNotifier->GetBufferBuilder().CreateVector(msg, len); - data["ppid"] = ppid; + auto notification = FBS::DataConsumer::CreateMessageNotification( + this->shared->channelNotifier->GetBufferBuilder(), ppid, data); - this->shared->payloadChannelNotifier->Emit(dataConsumer->id, "message", data, msg, len); + this->shared->channelNotifier->Emit( + dataConsumer->id, + FBS::Notification::Event::DATACONSUMER_MESSAGE, + FBS::Notification::Body::FBS_DataConsumer_MessageNotification, + notification); // Increase send transmission. RTC::Transport::DataSent(len); diff --git a/worker/src/RTC/IceCandidate.cpp b/worker/src/RTC/IceCandidate.cpp index 4d756c3a64..67af1a18e4 100644 --- a/worker/src/RTC/IceCandidate.cpp +++ b/worker/src/RTC/IceCandidate.cpp @@ -8,51 +8,60 @@ namespace RTC { /* Instance methods. */ - void IceCandidate::FillJson(json& jsonObject) const + flatbuffers::Offset IceCandidate::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add foundation. - jsonObject["foundation"] = this->foundation; + std::string protocol; - // Add priority. - jsonObject["priority"] = this->priority; - - // Add ip. - jsonObject["ip"] = this->ip; - - // Add protocol. switch (this->protocol) { case Protocol::UDP: - jsonObject["protocol"] = "udp"; + protocol = "udp"; break; case Protocol::TCP: - jsonObject["protocol"] = "tcp"; + protocol = "tcp"; break; } - // Add port. - jsonObject["port"] = this->port; + std::string type; - // Add type. switch (this->type) { case CandidateType::HOST: - jsonObject["type"] = "host"; + type = "host"; break; } - // Add tcpType. + std::string tcpType; + if (this->protocol == Protocol::TCP) { switch (this->tcpType) { case TcpCandidateType::PASSIVE: - jsonObject["tcpType"] = "passive"; + tcpType = "passive"; break; } } + + return FBS::WebRtcTransport::CreateIceCandidateDirect( + builder, + // foundation. + this->foundation.c_str(), + // priority. + this->priority, + // ip. + this->ip.c_str(), + // protocol. + protocol.c_str(), + // port. + this->port, + // type. + type.c_str(), + // tcpType. + tcpType.c_str()); } } // namespace RTC diff --git a/worker/src/RTC/PipeConsumer.cpp b/worker/src/RTC/PipeConsumer.cpp index f4f1d767ef..64dc90ad73 100644 --- a/worker/src/RTC/PipeConsumer.cpp +++ b/worker/src/RTC/PipeConsumer.cpp @@ -16,7 +16,7 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data) + const FBS::Transport::ConsumeRequest* data) : RTC::Consumer::Consumer(shared, id, producerId, listener, data, RTC::RtpParameters::Type::PIPE) { MS_TRACE(); @@ -37,8 +37,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelNotificationHandler*/ nullptr); } PipeConsumer::~PipeConsumer() @@ -56,61 +55,76 @@ namespace RTC this->mapSsrcRtpStream.clear(); } - void PipeConsumer::FillJson(json& jsonObject) const + flatbuffers::Offset PipeConsumer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); // Call the parent method. - RTC::Consumer::FillJson(jsonObject); + auto base = RTC::Consumer::FillBuffer(builder); // Add rtpStreams. - jsonObject["rtpStreams"] = json::array(); - auto jsonRtpStreamsIt = jsonObject.find("rtpStreams"); + std::vector> rtpStreams; + rtpStreams.reserve(this->rtpStreams.size()); - for (auto* rtpStream : this->rtpStreams) + for (const auto* rtpStream : this->rtpStreams) { - jsonRtpStreamsIt->emplace_back(json::value_t::object); + rtpStreams.emplace_back(rtpStream->FillBuffer(builder)); + } - auto& jsonEntry = (*jsonRtpStreamsIt)[jsonRtpStreamsIt->size() - 1]; + auto pipeConsumerDump = FBS::Consumer::CreatePipeConsumerDumpDirect(builder, base, &rtpStreams); - rtpStream->FillJson(jsonEntry); - } + return FBS::Consumer::CreateDumpResponse( + builder, + FBS::Consumer::DumpData::PipeConsumerDump, + pipeConsumerDump.Union(), + FBS::RtpParameters::Type(this->type)); } - void PipeConsumer::FillJsonStats(json& jsonArray) const + flatbuffers::Offset PipeConsumer::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); + std::vector> rtpStreams; + rtpStreams.reserve(this->rtpStreams.size()); + // Add stats of our send streams. for (auto* rtpStream : this->rtpStreams) { - jsonArray.emplace_back(json::value_t::object); - - auto& jsonEntry = jsonArray[jsonArray.size() - 1]; - - rtpStream->FillJsonStats(jsonEntry); + rtpStreams.emplace_back(rtpStream->FillBufferStats(builder)); } + + return FBS::Consumer::CreateGetStatsResponseDirect(builder, &rtpStreams); } - void PipeConsumer::FillJsonScore(json& jsonObject) const + flatbuffers::Offset PipeConsumer::FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); MS_ASSERT(this->producerRtpStreamScores, "producerRtpStreamScores not set"); // NOTE: Hardcoded values in PipeTransport. - jsonObject["score"] = 10; - jsonObject["producerScore"] = 10; - jsonObject["producerScores"] = *this->producerRtpStreamScores; + return FBS::Consumer::CreateConsumerScoreDirect(builder, 10, 10, this->producerRtpStreamScores); } void PipeConsumer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::CONSUMER_REQUEST_KEY_FRAME: + case Channel::ChannelRequest::Method::CONSUMER_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::FBS_Consumer_DumpResponse, dumpOffset); + + break; + } + + case Channel::ChannelRequest::Method::CONSUMER_REQUEST_KEY_FRAME: { if (IsActive()) RequestKeyFrame(); @@ -120,7 +134,7 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::CONSUMER_SET_PREFERRED_LAYERS: + case Channel::ChannelRequest::Method::CONSUMER_SET_PREFERRED_LAYERS: { // Do nothing. diff --git a/worker/src/RTC/PipeTransport.cpp b/worker/src/RTC/PipeTransport.cpp index 39bc2a0ead..2895d099f9 100644 --- a/worker/src/RTC/PipeTransport.cpp +++ b/worker/src/RTC/PipeTransport.cpp @@ -23,65 +23,25 @@ namespace RTC // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) PipeTransport::PipeTransport( - RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data) - : RTC::Transport::Transport(shared, id, listener, data) + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::PipeTransport::PipeTransportOptions* options) + : RTC::Transport::Transport(shared, id, listener, options->base()) { MS_TRACE(); - auto jsonListenIpIt = data.find("listenIp"); - - if (jsonListenIpIt == data.end()) - MS_THROW_TYPE_ERROR("missing listenIp"); - else if (!jsonListenIpIt->is_object()) - MS_THROW_TYPE_ERROR("wrong listenIp (not an object)"); - - auto jsonIpIt = jsonListenIpIt->find("ip"); - - if (jsonIpIt == jsonListenIpIt->end()) - MS_THROW_TYPE_ERROR("missing listenIp.ip"); - else if (!jsonIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenIp.ip (not an string)"); - - this->listenIp.ip.assign(jsonIpIt->get()); + this->listenIp.ip.assign(options->listenIp()->ip()->str()); // This may throw. Utils::IP::NormalizeIp(this->listenIp.ip); - auto jsonAnnouncedIpIt = jsonListenIpIt->find("announcedIp"); + if (flatbuffers::IsFieldPresent(options->listenIp(), FBS::Transport::ListenIp::VT_ANNOUNCEDIP)) + this->listenIp.announcedIp.assign(options->listenIp()->announcedIp()->str()); - if (jsonAnnouncedIpIt != jsonListenIpIt->end()) - { - if (!jsonAnnouncedIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenIp.announcedIp (not an string"); - - this->listenIp.announcedIp.assign(jsonAnnouncedIpIt->get()); - } + this->rtx = options->enableRtx(); - uint16_t port{ 0 }; - auto jsonPortIt = data.find("port"); - - if (jsonPortIt != data.end()) - { - if (!(jsonPortIt->is_number() && Utils::Json::IsPositiveInteger(*jsonPortIt))) - MS_THROW_TYPE_ERROR("wrong port (not a positive number)"); - - port = jsonPortIt->get(); - } - - auto jsonEnableRtxIt = data.find("enableRtx"); - - if (jsonEnableRtxIt != data.end() && jsonEnableRtxIt->is_boolean()) - this->rtx = jsonEnableRtxIt->get(); - - auto jsonEnableSrtpIt = data.find("enableSrtp"); - - // clang-format off - if ( - jsonEnableSrtpIt != data.end() && - jsonEnableSrtpIt->is_boolean() && - jsonEnableSrtpIt->get() - ) - // clang-format on + if (options->enableSrtp()) { this->srtpKey = Utils::Crypto::GetRandomString(PipeTransport::srtpMasterLength); this->srtpKeyBase64 = Utils::String::Base64Encode(this->srtpKey); @@ -90,8 +50,8 @@ namespace RTC try { // This may throw. - if (port != 0) - this->udpSocket = new RTC::UdpSocket(this, this->listenIp.ip, port); + if (options->port() != 0) + this->udpSocket = new RTC::UdpSocket(this, this->listenIp.ip, options->port()); else this->udpSocket = new RTC::UdpSocket(this, this->listenIp.ip); @@ -99,8 +59,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ this, - /*payloadChannelNotificationHandler*/ this); + /*channelNotificationHandler*/ this); } catch (const MediaSoupError& error) { @@ -132,85 +91,112 @@ namespace RTC this->srtpRecvSession = nullptr; } - void PipeTransport::FillJson(json& jsonObject) const + flatbuffers::Offset PipeTransport::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Call the parent method. - RTC::Transport::FillJson(jsonObject); - // Add tuple. + flatbuffers::Offset tuple; + if (this->tuple) { - this->tuple->FillJson(jsonObject["tuple"]); + tuple = this->tuple->FillBuffer(builder); } else { - jsonObject["tuple"] = json::object(); - auto jsonTupleIt = jsonObject.find("tuple"); + std::string localIp; if (this->listenIp.announcedIp.empty()) - (*jsonTupleIt)["localIp"] = this->udpSocket->GetLocalIp(); + localIp = this->udpSocket->GetLocalIp(); else - (*jsonTupleIt)["localIp"] = this->listenIp.announcedIp; + localIp = this->listenIp.announcedIp; - (*jsonTupleIt)["localPort"] = this->udpSocket->GetLocalPort(); - (*jsonTupleIt)["protocol"] = "udp"; + tuple = FBS::Transport::CreateTupleDirect( + builder, localIp.c_str(), this->udpSocket->GetLocalPort(), "", 0, "udp"); } - // Add rtx. - jsonObject["rtx"] = this->rtx; - // Add srtpParameters. + flatbuffers::Offset srtpParameters; + if (HasSrtp()) { - jsonObject["srtpParameters"] = json::object(); - auto jsonSrtpParametersIt = jsonObject.find("srtpParameters"); - - (*jsonSrtpParametersIt)["cryptoSuite"] = PipeTransport::srtpCryptoSuiteString; - (*jsonSrtpParametersIt)["keyBase64"] = this->srtpKeyBase64; + srtpParameters = FBS::Transport::CreateSrtpParametersDirect( + builder, PipeTransport::srtpCryptoSuiteString.c_str(), this->srtpKeyBase64.c_str()); } + + // Add base transport dump. + auto base = Transport::FillBuffer(builder); + + return FBS::PipeTransport::CreateDumpResponse(builder, base, tuple, this->rtx, srtpParameters); } - void PipeTransport::FillJsonStats(json& jsonArray) + flatbuffers::Offset PipeTransport::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); - // Call the parent method. - RTC::Transport::FillJsonStats(jsonArray); - - auto& jsonObject = jsonArray[0]; - - // Add type. - jsonObject["type"] = "pipe-transport"; + // Add tuple. + flatbuffers::Offset tuple; if (this->tuple) { - this->tuple->FillJson(jsonObject["tuple"]); + tuple = this->tuple->FillBuffer(builder); } else { - // Add tuple. - jsonObject["tuple"] = json::object(); - auto jsonTupleIt = jsonObject.find("tuple"); + std::string localIp; if (this->listenIp.announcedIp.empty()) - (*jsonTupleIt)["localIp"] = this->udpSocket->GetLocalIp(); + localIp = this->udpSocket->GetLocalIp(); else - (*jsonTupleIt)["localIp"] = this->listenIp.announcedIp; - - (*jsonTupleIt)["localPort"] = this->udpSocket->GetLocalPort(); - (*jsonTupleIt)["protocol"] = "udp"; + localIp = this->listenIp.announcedIp; + + tuple = FBS::Transport::CreateTupleDirect( + builder, + // localIp. + localIp.c_str(), + // localPort, + this->udpSocket->GetLocalPort(), + // remoteIp. + nullptr, + // remotePort. + 0, + // protocol. + "udp"); } + + // Base Transport stats. + auto base = Transport::FillBufferStats(builder); + + return FBS::PipeTransport::CreateGetStatsResponse(builder, base, tuple); } void PipeTransport::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::TRANSPORT_CONNECT: + case Channel::ChannelRequest::Method::TRANSPORT_GET_STATS: + { + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::FBS_PipeTransport_GetStatsResponse, responseOffset); + + break; + } + + case Channel::ChannelRequest::Method::TRANSPORT_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::FBS_PipeTransport_DumpResponse, dumpOffset); + + break; + } + + case Channel::ChannelRequest::Method::PIPE_TRANSPORT_CONNECT: { // Ensure this method is not called twice. if (this->tuple) @@ -222,56 +208,32 @@ namespace RTC uint16_t port{ 0u }; std::string srtpKeyBase64; - auto jsonSrtpParametersIt = request->data.find("srtpParameters"); + const auto* body = request->data->body_as(); + + auto srtpParametersPresent = + flatbuffers::IsFieldPresent(body, FBS::PipeTransport::ConnectRequest::VT_SRTPPARAMETERS); - if (!HasSrtp() && jsonSrtpParametersIt != request->data.end()) + if (!HasSrtp() && srtpParametersPresent) { MS_THROW_TYPE_ERROR("invalid srtpParameters (SRTP not enabled)"); } else if (HasSrtp()) { - // clang-format off - if ( - jsonSrtpParametersIt == request->data.end() || - !jsonSrtpParametersIt->is_object() - ) - // clang-format on + if (!srtpParametersPresent) { MS_THROW_TYPE_ERROR("missing srtpParameters (SRTP enabled)"); } - auto jsonCryptoSuiteIt = jsonSrtpParametersIt->find("cryptoSuite"); - - // clang-format off - if ( - jsonCryptoSuiteIt == jsonSrtpParametersIt->end() || - !jsonCryptoSuiteIt->is_string() - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing srtpParameters.cryptoSuite)"); - } + const auto* srtpParameters = body->srtpParameters(); // NOTE: We just use AEAD_AES_256_GCM as SRTP crypto suite in // PipeTransport. - if (jsonCryptoSuiteIt->get() != PipeTransport::srtpCryptoSuiteString) + if (srtpParameters->cryptoSuite()->str() != PipeTransport::srtpCryptoSuiteString) { MS_THROW_TYPE_ERROR("invalid/unsupported srtpParameters.cryptoSuite"); } - auto jsonKeyBase64It = jsonSrtpParametersIt->find("keyBase64"); - - // clang-format off - if ( - jsonKeyBase64It == jsonSrtpParametersIt->end() || - !jsonKeyBase64It->is_string() - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing srtpParameters.keyBase64)"); - } - - srtpKeyBase64 = jsonKeyBase64It->get(); + srtpKeyBase64 = srtpParameters->keyBase64()->str(); size_t outLen; // This may throw. @@ -322,29 +284,20 @@ namespace RTC delete[] srtpRemoteKey; } - auto jsonIpIt = request->data.find("ip"); - - if (jsonIpIt == request->data.end() || !jsonIpIt->is_string()) + if (!flatbuffers::IsFieldPresent(body, FBS::PipeTransport::ConnectRequest::VT_IP)) MS_THROW_TYPE_ERROR("missing ip"); - ip = jsonIpIt->get(); + ip = body->ip()->str(); // This may throw. Utils::IP::NormalizeIp(ip); - auto jsonPortIt = request->data.find("port"); - - // clang-format off - if ( - jsonPortIt == request->data.end() || - !Utils::Json::IsPositiveInteger(*jsonPortIt) - ) - // clang-format on + if (!body->port().has_value()) { MS_THROW_TYPE_ERROR("missing port"); } - port = jsonPortIt->get(); + port = body->port().value(); int err; @@ -403,12 +356,12 @@ namespace RTC throw; } - // Tell the caller about the selected local DTLS role. - json data = json::object(); + auto tupleOffset = this->tuple->FillBuffer(request->GetBufferBuilder()); - this->tuple->FillJson(data["tuple"]); + auto responseOffset = + FBS::PipeTransport::CreateConnectResponse(request->GetBufferBuilder(), tupleOffset); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_PipeTransport_ConnectResponse, responseOffset); // Assume we are connected (there is no much more we can do to know it) // and tell the parent class. @@ -425,7 +378,7 @@ namespace RTC } } - void PipeTransport::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) + void PipeTransport::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); diff --git a/worker/src/RTC/PlainTransport.cpp b/worker/src/RTC/PlainTransport.cpp index a90ecdd8dc..95e931ede9 100644 --- a/worker/src/RTC/PlainTransport.cpp +++ b/worker/src/RTC/PlainTransport.cpp @@ -44,90 +44,34 @@ namespace RTC /* Instance methods. */ - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) - PlainTransport::PlainTransport(RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data) - : RTC::Transport::Transport(shared, id, listener, data) + PlainTransport::PlainTransport( + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::PlainTransport::PlainTransportOptions* options) + : RTC::Transport::Transport(shared, id, listener, options->base()) { MS_TRACE(); - auto jsonListenIpIt = data.find("listenIp"); - - if (jsonListenIpIt == data.end()) - MS_THROW_TYPE_ERROR("missing listenIp"); - else if (!jsonListenIpIt->is_object()) - MS_THROW_TYPE_ERROR("wrong listenIp (not an object)"); - - auto jsonIpIt = jsonListenIpIt->find("ip"); - - if (jsonIpIt == jsonListenIpIt->end()) - MS_THROW_TYPE_ERROR("missing listenIp.ip"); - else if (!jsonIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenIp.ip (not an string)"); - - this->listenIp.ip.assign(jsonIpIt->get()); + this->listenIp.ip.assign(options->listenIp()->ip()->str()); // This may throw. Utils::IP::NormalizeIp(this->listenIp.ip); - auto jsonAnnouncedIpIt = jsonListenIpIt->find("announcedIp"); - - if (jsonAnnouncedIpIt != jsonListenIpIt->end()) - { - if (!jsonAnnouncedIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenIp.announcedIp (not an string"); - - this->listenIp.announcedIp.assign(jsonAnnouncedIpIt->get()); - } - - uint16_t port{ 0 }; - auto jsonPortIt = data.find("port"); - - if (jsonPortIt != data.end()) - { - if (!(jsonPortIt->is_number() && Utils::Json::IsPositiveInteger(*jsonPortIt))) - MS_THROW_TYPE_ERROR("wrong port (not a positive number)"); - - port = jsonPortIt->get(); - } - - auto jsonRtcpMuxIt = data.find("rtcpMux"); - - if (jsonRtcpMuxIt != data.end()) - { - if (!jsonRtcpMuxIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong rtcpMux (not a boolean)"); - - this->rtcpMux = jsonRtcpMuxIt->get(); - } - - auto jsonComediaIt = data.find("comedia"); - - if (jsonComediaIt != data.end()) - { - if (!jsonComediaIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong comedia (not a boolean)"); - - this->comedia = jsonComediaIt->get(); - } + if (flatbuffers::IsFieldPresent(options->listenIp(), FBS::Transport::ListenIp::VT_ANNOUNCEDIP)) + this->listenIp.announcedIp.assign(options->listenIp()->announcedIp()->str()); - auto jsonEnableSrtpIt = data.find("enableSrtp"); + this->rtcpMux = options->rtcpMux(); + this->comedia = options->comedia(); - // clang-format off - if ( - jsonEnableSrtpIt != data.end() && - jsonEnableSrtpIt->is_boolean() && - jsonEnableSrtpIt->get() - ) - // clang-format on + if (options->enableSrtp()) { - auto jsonSrtpCryptoSuiteIt = data.find("srtpCryptoSuite"); - - if (jsonSrtpCryptoSuiteIt == data.end() || !jsonSrtpCryptoSuiteIt->is_string()) + if (!flatbuffers::IsFieldPresent( + options, FBS::PlainTransport::PlainTransportOptions::VT_SRTPCRYPTOSUITE)) MS_THROW_TYPE_ERROR("missing srtpCryptoSuite)"); // Ensure it's a crypto suite supported by us. - auto it = - PlainTransport::string2SrtpCryptoSuite.find(jsonSrtpCryptoSuiteIt->get()); + auto it = PlainTransport::string2SrtpCryptoSuite.find(options->srtpCryptoSuite()->str()); if (it == PlainTransport::string2SrtpCryptoSuite.end()) MS_THROW_TYPE_ERROR("invalid/unsupported srtpCryptoSuite"); @@ -172,8 +116,8 @@ namespace RTC try { // This may throw. - if (port != 0) - this->udpSocket = new RTC::UdpSocket(this, this->listenIp.ip, port); + if (options->port() != 0) + this->udpSocket = new RTC::UdpSocket(this, this->listenIp.ip, options->port()); else this->udpSocket = new RTC::UdpSocket(this, this->listenIp.ip); @@ -187,8 +131,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ this, - /*payloadChannelNotificationHandler*/ this); + /*channelNotificationHandler*/ this); } catch (const MediaSoupError& error) { @@ -227,122 +170,151 @@ namespace RTC this->srtpRecvSession = nullptr; } - void PlainTransport::FillJson(json& jsonObject) const + flatbuffers::Offset PlainTransport::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Call the parent method. - RTC::Transport::FillJson(jsonObject); - - // Add rtcpMux. - jsonObject["rtcpMux"] = this->rtcpMux; - - // Add comedia. - jsonObject["comedia"] = this->comedia; - // Add tuple. + flatbuffers::Offset tuple; + if (this->tuple) { - this->tuple->FillJson(jsonObject["tuple"]); + tuple = this->tuple->FillBuffer(builder); } else { - jsonObject["tuple"] = json::object(); - auto jsonTupleIt = jsonObject.find("tuple"); + std::string localIp; if (this->listenIp.announcedIp.empty()) - (*jsonTupleIt)["localIp"] = this->udpSocket->GetLocalIp(); + localIp = this->udpSocket->GetLocalIp(); else - (*jsonTupleIt)["localIp"] = this->listenIp.announcedIp; + localIp = this->listenIp.announcedIp; - (*jsonTupleIt)["localPort"] = this->udpSocket->GetLocalPort(); - (*jsonTupleIt)["protocol"] = "udp"; + tuple = FBS::Transport::CreateTupleDirect( + builder, localIp.c_str(), this->udpSocket->GetLocalPort(), "", 0, "udp"); } // Add rtcpTuple. + flatbuffers::Offset rtcpTuple; + if (!this->rtcpMux) { if (this->rtcpTuple) { - this->rtcpTuple->FillJson(jsonObject["rtcpTuple"]); + rtcpTuple = this->rtcpTuple->FillBuffer(builder); } else { - jsonObject["rtcpTuple"] = json::object(); - auto jsonRtcpTupleIt = jsonObject.find("rtcpTuple"); + std::string localIp; if (this->listenIp.announcedIp.empty()) - (*jsonRtcpTupleIt)["localIp"] = this->rtcpUdpSocket->GetLocalIp(); + localIp = this->rtcpUdpSocket->GetLocalIp(); else - (*jsonRtcpTupleIt)["localIp"] = this->listenIp.announcedIp; + localIp = this->listenIp.announcedIp; - (*jsonRtcpTupleIt)["localPort"] = this->rtcpUdpSocket->GetLocalPort(); - (*jsonRtcpTupleIt)["protocol"] = "udp"; + rtcpTuple = FBS::Transport::CreateTupleDirect( + builder, localIp.c_str(), this->rtcpUdpSocket->GetLocalPort(), "", 0, "udp"); } } // Add srtpParameters. + flatbuffers::Offset srtpParameters; + if (HasSrtp()) { - jsonObject["srtpParameters"] = json::object(); - auto jsonSrtpParametersIt = jsonObject.find("srtpParameters"); - - (*jsonSrtpParametersIt)["cryptoSuite"] = - PlainTransport::srtpCryptoSuite2String[this->srtpCryptoSuite]; - (*jsonSrtpParametersIt)["keyBase64"] = this->srtpKeyBase64; + srtpParameters = FBS::Transport::CreateSrtpParametersDirect( + builder, + PlainTransport::srtpCryptoSuite2String[this->srtpCryptoSuite].c_str(), + this->srtpKeyBase64.c_str()); } + + // Add base transport dump. + auto base = Transport::FillBuffer(builder); + + return FBS::PlainTransport::CreateDumpResponse( + builder, base, this->rtcpMux, this->comedia, tuple, rtcpTuple, srtpParameters); } - void PlainTransport::FillJsonStats(json& jsonArray) + flatbuffers::Offset PlainTransport::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); - // Call the parent method. - RTC::Transport::FillJsonStats(jsonArray); - - auto& jsonObject = jsonArray[0]; - - // Add type. - jsonObject["type"] = "plain-rtp-transport"; - - // Add rtcpMux. - jsonObject["rtcpMux"] = this->rtcpMux; - - // Add comedia. - jsonObject["comedia"] = this->comedia; + // Add tuple. + flatbuffers::Offset tuple; if (this->tuple) { - // Add tuple. - this->tuple->FillJson(jsonObject["tuple"]); + tuple = this->tuple->FillBuffer(builder); } else { - // Add tuple. - jsonObject["tuple"] = json::object(); - auto jsonTupleIt = jsonObject.find("tuple"); + std::string localIp; if (this->listenIp.announcedIp.empty()) - (*jsonTupleIt)["localIp"] = this->udpSocket->GetLocalIp(); + localIp = this->udpSocket->GetLocalIp(); else - (*jsonTupleIt)["localIp"] = this->listenIp.announcedIp; - - (*jsonTupleIt)["localPort"] = this->udpSocket->GetLocalPort(); - (*jsonTupleIt)["protocol"] = "udp"; + localIp = this->listenIp.announcedIp; + + tuple = FBS::Transport::CreateTupleDirect( + builder, + // localIp. + localIp.c_str(), + // localPort, + this->udpSocket->GetLocalPort(), + // remoteIp. + nullptr, + // remotePort. + 0, + // protocol. + "udp" + ); } // Add rtcpTuple. + flatbuffers::Offset rtcpTuple; + if (!this->rtcpMux && this->rtcpTuple) - this->rtcpTuple->FillJson(jsonObject["rtcpTuple"]); + rtcpTuple = this->rtcpTuple->FillBuffer(builder); + + // Base Transport stats. + auto base = Transport::FillBufferStats(builder); + + return FBS::PlainTransport::CreateGetStatsResponse( + builder, + base, + this->rtcpMux, + this->comedia, + tuple, + rtcpTuple); } void PlainTransport::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::TRANSPORT_CONNECT: + case Channel::ChannelRequest::Method::TRANSPORT_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::FBS_PlainTransport_DumpResponse, dumpOffset); + + break; + } + + case Channel::ChannelRequest::Method::TRANSPORT_GET_STATS: + { + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::FBS_PlainTransport_GetStatsResponse, responseOffset); + + break; + } + + case Channel::ChannelRequest::Method::PLAIN_TRANSPORT_CONNECT: { // Ensure this method is not called twice. if (this->connectCalled) @@ -355,39 +327,26 @@ namespace RTC uint16_t rtcpPort{ 0u }; std::string srtpKeyBase64; - auto jsonSrtpParametersIt = request->data.find("srtpParameters"); + const auto *body = request->data->body_as(); + + auto srtpParametersPresent = flatbuffers::IsFieldPresent( + body, FBS::PlainTransport::ConnectRequest::VT_SRTPPARAMETERS); - if (!HasSrtp() && jsonSrtpParametersIt != request->data.end()) + if (!HasSrtp() && srtpParametersPresent) { MS_THROW_TYPE_ERROR("invalid srtpParameters (SRTP not enabled)"); } else if (HasSrtp()) { - // clang-format off - if ( - jsonSrtpParametersIt == request->data.end() || - !jsonSrtpParametersIt->is_object() - ) - // clang-format on + if (!srtpParametersPresent) { MS_THROW_TYPE_ERROR("missing srtpParameters (SRTP enabled)"); } - auto jsonCryptoSuiteIt = jsonSrtpParametersIt->find("cryptoSuite"); - - // clang-format off - if ( - jsonCryptoSuiteIt == jsonSrtpParametersIt->end() || - !jsonCryptoSuiteIt->is_string() - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing srtpParameters.cryptoSuite)"); - } - + const auto *srtpParameters = body->srtpParameters(); // Ensure it's a crypto suite supported by us. auto it = - PlainTransport::string2SrtpCryptoSuite.find(jsonCryptoSuiteIt->get()); + PlainTransport::string2SrtpCryptoSuite.find(srtpParameters->cryptoSuite()->str()); if (it == PlainTransport::string2SrtpCryptoSuite.end()) MS_THROW_TYPE_ERROR("invalid/unsupported srtpParameters.cryptoSuite"); @@ -433,19 +392,7 @@ namespace RTC this->srtpKeyBase64 = Utils::String::Base64Encode(this->srtpKey); } - auto jsonKeyBase64It = jsonSrtpParametersIt->find("keyBase64"); - - // clang-format off - if ( - jsonKeyBase64It == jsonSrtpParametersIt->end() || - !jsonKeyBase64It->is_string() - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing srtpParameters.keyBase64)"); - } - - srtpKeyBase64 = jsonKeyBase64It->get(); + srtpKeyBase64 = srtpParameters->keyBase64()->str(); size_t outLen; // This may throw. @@ -498,43 +445,27 @@ namespace RTC if (!this->comedia) { - auto jsonIpIt = request->data.find("ip"); - - if (jsonIpIt == request->data.end() || !jsonIpIt->is_string()) + if (!flatbuffers::IsFieldPresent(body, FBS::PlainTransport::ConnectRequest::VT_IP)) MS_THROW_TYPE_ERROR("missing ip"); - ip = jsonIpIt->get(); + ip = body->ip()->str(); // This may throw. Utils::IP::NormalizeIp(ip); - auto jsonPortIt = request->data.find("port"); - - // clang-format off - if ( - jsonPortIt == request->data.end() || - !Utils::Json::IsPositiveInteger(*jsonPortIt) - ) - // clang-format on + if (!body->port().has_value()) { MS_THROW_TYPE_ERROR("missing port"); } - port = jsonPortIt->get(); + port = body->port().value(); - auto jsonRtcpPortIt = request->data.find("rtcpPort"); - - // clang-format off - if ( - jsonRtcpPortIt != request->data.end() && - Utils::Json::IsPositiveInteger(*jsonRtcpPortIt) - ) - // clang-format on + if (body->rtcpPort().has_value()) { if (this->rtcpMux) MS_THROW_TYPE_ERROR("cannot set rtcpPort with rtcpMux enabled"); - rtcpPort = jsonRtcpPortIt->get(); + rtcpPort = body->rtcpPort().value(); } else { @@ -651,25 +582,30 @@ namespace RTC this->connectCalled = true; // Tell the caller about the selected local DTLS role. - json data = json::object(); + flatbuffers::Offset tupleOffset; + flatbuffers::Offset rtcpTupleOffset; + flatbuffers::Offset srtpParametersOffset; if (this->tuple) - this->tuple->FillJson(data["tuple"]); + tupleOffset = this->tuple->FillBuffer(request->GetBufferBuilder()); if (!this->rtcpMux && this->rtcpTuple) - this->rtcpTuple->FillJson(data["rtcpTuple"]); + rtcpTupleOffset = this->rtcpTuple->FillBuffer(request->GetBufferBuilder()); if (HasSrtp()) { - data["srtpParameters"] = json::object(); - auto jsonSrtpParametersIt = data.find("srtpParameters"); - - (*jsonSrtpParametersIt)["cryptoSuite"] = - PlainTransport::srtpCryptoSuite2String[this->srtpCryptoSuite]; - (*jsonSrtpParametersIt)["keyBase64"] = this->srtpKeyBase64; + srtpParametersOffset = FBS::Transport::CreateSrtpParametersDirect( + request->GetBufferBuilder(), + PlainTransport::srtpCryptoSuite2String[this->srtpCryptoSuite].c_str(), + this->srtpKeyBase64.c_str() + ); } - request->Accept(data); + auto responseOffset = + FBS::PlainTransport::CreateConnectResponse( + request->GetBufferBuilder(), tupleOffset, rtcpTupleOffset, srtpParametersOffset); + + request->Accept(FBS::Response::Body::FBS_PlainTransport_ConnectResponse, responseOffset); // Assume we are connected (there is no much more we can do to know it) // and tell the parent class. @@ -686,7 +622,7 @@ namespace RTC } } - void PlainTransport::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) + void PlainTransport::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); @@ -937,11 +873,7 @@ namespace RTC if (!wasConnected) { // Notify the Node PlainTransport. - json data = json::object(); - - this->tuple->FillJson(data["tuple"]); - - this->shared->channelNotifier->Emit(this->id, "tuple", data); + EmitTuple(); RTC::Transport::Connected(); } @@ -1004,11 +936,7 @@ namespace RTC if (!wasConnected) { // Notify the Node PlainTransport. - json data = json::object(); - - this->tuple->FillJson(data["tuple"]); - - this->shared->channelNotifier->Emit(this->id, "tuple", data); + EmitTuple(); RTC::Transport::Connected(); } @@ -1032,11 +960,7 @@ namespace RTC this->rtcpTuple->SetLocalAnnouncedIp(this->listenIp.announcedIp); // Notify the Node PlainTransport. - json data = json::object(); - - this->rtcpTuple->FillJson(data["rtcpTuple"]); - - this->shared->channelNotifier->Emit(this->id, "rtcptuple", data); + EmitRtcpTuple(); } // If RTCP-mux verify that the packet's tuple matches our RTP tuple. else if (this->rtcpMux && !this->tuple->Compare(tuple)) @@ -1094,11 +1018,7 @@ namespace RTC if (!wasConnected) { // Notify the Node PlainTransport. - json data = json::object(); - - this->tuple->FillJson(data["tuple"]); - - this->shared->channelNotifier->Emit(this->id, "tuple", data); + EmitTuple(); RTC::Transport::Connected(); } @@ -1116,6 +1036,34 @@ namespace RTC RTC::Transport::ReceiveSctpData(data, len); } + inline void PlainTransport::EmitTuple() const + { + auto tuple = this->tuple->FillBuffer(this->shared->channelNotifier->GetBufferBuilder()); + auto notification = FBS::PlainTransport::CreateTupleNotification( + this->shared->channelNotifier->GetBufferBuilder(), + tuple); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::PLAINTRANSPORT_TUPLE, + FBS::Notification::Body::FBS_PlainTransport_TupleNotification, + notification); + } + + inline void PlainTransport::EmitRtcpTuple() const + { + auto rtcpTuple = this->rtcpTuple->FillBuffer(this->shared->channelNotifier->GetBufferBuilder()); + auto notification = FBS::PlainTransport::CreateRtcpTupleNotification( + this->shared->channelNotifier->GetBufferBuilder(), + rtcpTuple); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::PLAINTRANSPORT_RTCP_TUPLE, + FBS::Notification::Body::FBS_PlainTransport_RtcpTupleNotification, + notification); + } + inline void PlainTransport::OnUdpSocketPacketReceived( RTC::UdpSocket* socket, const uint8_t* data, size_t len, const struct sockaddr* remoteAddr) { diff --git a/worker/src/RTC/PortManager.cpp b/worker/src/RTC/PortManager.cpp index 5269fced06..2b634edf5e 100644 --- a/worker/src/RTC/PortManager.cpp +++ b/worker/src/RTC/PortManager.cpp @@ -608,55 +608,4 @@ namespace RTC return emptyPorts; } - - void PortManager::FillJson(json& jsonObject) - { - MS_TRACE(); - - // Add udp. - jsonObject["udp"] = json::object(); - auto jsonUdpIt = jsonObject.find("udp"); - - for (auto& kv : PortManager::mapUdpIpPorts) - { - const auto& ip = kv.first; - auto& ports = kv.second; - - (*jsonUdpIt)[ip] = json::array(); - auto jsonIpIt = jsonUdpIt->find(ip); - - for (size_t i{ 0 }; i < ports.size(); ++i) - { - if (!ports[i]) - continue; - - auto port = static_cast(i + Settings::configuration.rtcMinPort); - - jsonIpIt->push_back(port); - } - } - - // Add tcp. - jsonObject["tcp"] = json::object(); - auto jsonTcpIt = jsonObject.find("tcp"); - - for (auto& kv : PortManager::mapTcpIpPorts) - { - const auto& ip = kv.first; - auto& ports = kv.second; - - (*jsonTcpIt)[ip] = json::array(); - auto jsonIpIt = jsonTcpIt->find(ip); - - for (size_t i{ 0 }; i < ports.size(); ++i) - { - if (!ports[i]) - continue; - - auto port = static_cast(i + Settings::configuration.rtcMinPort); - - jsonIpIt->emplace_back(port); - } - } - } } // namespace RTC diff --git a/worker/src/RTC/Producer.cpp b/worker/src/RTC/Producer.cpp index 1c0e674a8d..b0113e87ec 100644 --- a/worker/src/RTC/Producer.cpp +++ b/worker/src/RTC/Producer.cpp @@ -28,35 +28,24 @@ namespace RTC /* Instance methods. */ Producer::Producer( - RTC::Shared* shared, const std::string& id, RTC::Producer::Listener* listener, json& data) + RTC::Shared* shared, + const std::string& id, + RTC::Producer::Listener* listener, + const FBS::Transport::ProduceRequest* data) : id(id), shared(shared), listener(listener) { MS_TRACE(); - auto jsonKindIt = data.find("kind"); - - if (jsonKindIt == data.end() || !jsonKindIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing kind"); - } - // This may throw. - this->kind = RTC::Media::GetKind(jsonKindIt->get()); + this->kind = RTC::Media::Kind(data->kind()); if (this->kind == RTC::Media::Kind::ALL) { MS_THROW_TYPE_ERROR("invalid empty kind"); } - auto jsonRtpParametersIt = data.find("rtpParameters"); - - if (jsonRtpParametersIt == data.end() || !jsonRtpParametersIt->is_object()) - { - MS_THROW_TYPE_ERROR("missing rtpParameters"); - } - // This may throw. - this->rtpParameters = RTC::RtpParameters(*jsonRtpParametersIt); + this->rtpParameters = RTC::RtpParameters(data->rtpParameters()); // Evaluate type. this->type = RTC::RtpParameters::GetType(this->rtpParameters); @@ -77,102 +66,34 @@ namespace RTC RTC::RtpParameters::GetTypeString(this->type).c_str()); } - auto jsonRtpMappingIt = data.find("rtpMapping"); - - if (jsonRtpMappingIt == data.end() || !jsonRtpMappingIt->is_object()) - { - MS_THROW_TYPE_ERROR("missing rtpMapping"); - } - - auto jsonCodecsIt = jsonRtpMappingIt->find("codecs"); - - if (jsonCodecsIt == jsonRtpMappingIt->end() || !jsonCodecsIt->is_array()) - { - MS_THROW_TYPE_ERROR("missing rtpMapping.codecs"); - } - - for (auto& codec : *jsonCodecsIt) + for (const auto& codec : *data->rtpMapping()->codecs()) { - if (!codec.is_object()) - { - MS_THROW_TYPE_ERROR("wrong entry in rtpMapping.codecs (not an object)"); - } - - auto jsonPayloadTypeIt = codec.find("payloadType"); - - // clang-format off - if ( - jsonPayloadTypeIt == codec.end() || - !Utils::Json::IsPositiveInteger(*jsonPayloadTypeIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("wrong entry in rtpMapping.codecs (missing payloadType)"); - } - - auto jsonMappedPayloadTypeIt = codec.find("mappedPayloadType"); - - // clang-format off - if ( - jsonMappedPayloadTypeIt == codec.end() || - !Utils::Json::IsPositiveInteger(*jsonMappedPayloadTypeIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("wrong entry in rtpMapping.codecs (missing mappedPayloadType)"); - } - - this->rtpMapping.codecs[jsonPayloadTypeIt->get()] = - jsonMappedPayloadTypeIt->get(); + this->rtpMapping.codecs[codec->payloadType()] = codec->mappedPayloadType(); } - auto jsonEncodingsIt = jsonRtpMappingIt->find("encodings"); + const auto* encodings = data->rtpMapping()->encodings(); - if (jsonEncodingsIt == jsonRtpMappingIt->end() || !jsonEncodingsIt->is_array()) - { - MS_THROW_TYPE_ERROR("missing rtpMapping.encodings"); - } + this->rtpMapping.encodings.reserve(encodings->size()); - this->rtpMapping.encodings.reserve(jsonEncodingsIt->size()); - - for (auto& encoding : *jsonEncodingsIt) + for (const auto& encoding : *encodings) { - if (!encoding.is_object()) - { - MS_THROW_TYPE_ERROR("wrong entry in rtpMapping.encodings"); - } - this->rtpMapping.encodings.emplace_back(); auto& encodingMapping = this->rtpMapping.encodings.back(); // ssrc is optional. - auto jsonSsrcIt = encoding.find("ssrc"); - - // clang-format off - if ( - jsonSsrcIt != encoding.end() && - Utils::Json::IsPositiveInteger(*jsonSsrcIt) - ) - // clang-format on + if (encoding->ssrc().has_value()) { - encodingMapping.ssrc = jsonSsrcIt->get(); + encodingMapping.ssrc = encoding->ssrc().value(); } // rid is optional. - auto jsonRidIt = encoding.find("rid"); - - if (jsonRidIt != encoding.end() && jsonRidIt->is_string()) - { - encodingMapping.rid = jsonRidIt->get(); - } - // However ssrc or rid must be present (if more than 1 encoding). // clang-format off if ( - jsonEncodingsIt->size() > 1 && - jsonSsrcIt == encoding.end() && - jsonRidIt == encoding.end() + encodings->size() > 1 && + !encoding->ssrc().has_value() && + !flatbuffers::IsFieldPresent(encoding, FBS::RtpParameters::EncodingMapping::VT_RID) ) // clang-format on { @@ -183,9 +104,9 @@ namespace RTC // clang-format off if ( this->rtpParameters.mid.empty() && - jsonEncodingsIt->size() == 1 && - jsonSsrcIt == encoding.end() && - jsonRidIt == encoding.end() + encodings->size() == 1 && + !encoding->ssrc().has_value() && + !flatbuffers::IsFieldPresent(encoding, FBS::RtpParameters::EncodingMapping::VT_RID) ) // clang-format on { @@ -194,27 +115,15 @@ namespace RTC } // mappedSsrc is mandatory. - auto jsonMappedSsrcIt = encoding.find("mappedSsrc"); - - // clang-format off - if ( - jsonMappedSsrcIt == encoding.end() || - !Utils::Json::IsPositiveInteger(*jsonMappedSsrcIt) - ) - // clang-format on + if (!encoding->mappedSsrc()) { MS_THROW_TYPE_ERROR("wrong entry in rtpMapping.encodings (missing mappedSsrc)"); } - encodingMapping.mappedSsrc = jsonMappedSsrcIt->get(); + encodingMapping.mappedSsrc = encoding->mappedSsrc(); } - auto jsonPausedIt = data.find("paused"); - - if (jsonPausedIt != data.end() && jsonPausedIt->is_boolean()) - { - this->paused = jsonPausedIt->get(); - } + this->paused = data->paused(); // The number of encodings in rtpParameters must match the number of encodings // in rtpMapping. @@ -298,18 +207,7 @@ namespace RTC // Create a KeyFrameRequestManager. if (this->kind == RTC::Media::Kind::VIDEO) { - auto jsonKeyFrameRequestDelayIt = data.find("keyFrameRequestDelay"); - uint32_t keyFrameRequestDelay = 0u; - - // clang-format off - if ( - jsonKeyFrameRequestDelayIt != data.end() && - jsonKeyFrameRequestDelayIt->is_number_integer() - ) - // clang-format on - { - keyFrameRequestDelay = jsonKeyFrameRequestDelayIt->get(); - } + auto keyFrameRequestDelay = data->keyFrameRequestDelay(); this->keyFrameRequestManager = new RTC::KeyFrameRequestManager(this, keyFrameRequestDelay); } @@ -318,8 +216,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ this); + /*channelNotificationHandler*/ this); } Producer::~Producer() @@ -347,165 +244,121 @@ namespace RTC delete this->keyFrameRequestManager; } - void Producer::FillJson(json& jsonObject) const + flatbuffers::Offset Producer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add id. - jsonObject["id"] = this->id; - - // Add kind. - jsonObject["kind"] = RTC::Media::GetString(this->kind); - // Add rtpParameters. - this->rtpParameters.FillJson(jsonObject["rtpParameters"]); - - // Add type. - jsonObject["type"] = RTC::RtpParameters::GetTypeString(this->type); - - // Add rtpMapping. - jsonObject["rtpMapping"] = json::object(); - auto jsonRtpMappingIt = jsonObject.find("rtpMapping"); + auto rtpParameters = this->rtpParameters.FillBuffer(builder); // Add rtpMapping.codecs. - { - (*jsonRtpMappingIt)["codecs"] = json::array(); - auto jsonCodecsIt = jsonRtpMappingIt->find("codecs"); - size_t idx{ 0 }; + std::vector> codecs; - for (const auto& kv : this->rtpMapping.codecs) - { - jsonCodecsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonCodecsIt)[idx]; - auto payloadType = kv.first; - auto mappedPayloadType = kv.second; - - jsonEntry["payloadType"] = payloadType; - jsonEntry["mappedPayloadType"] = mappedPayloadType; - - ++idx; - } + for (const auto& kv : this->rtpMapping.codecs) + { + codecs.emplace_back(FBS::RtpParameters::CreateCodecMapping(builder, kv.first, kv.second)); } // Add rtpMapping.encodings. - { - (*jsonRtpMappingIt)["encodings"] = json::array(); - auto jsonEncodingsIt = jsonRtpMappingIt->find("encodings"); + std::vector> encodings; + encodings.reserve(this->rtpMapping.encodings.size()); - for (size_t i{ 0 }; i < this->rtpMapping.encodings.size(); ++i) - { - jsonEncodingsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonEncodingsIt)[i]; - const auto& encodingMapping = this->rtpMapping.encodings[i]; - - if (!encodingMapping.rid.empty()) - jsonEntry["rid"] = encodingMapping.rid; - else - jsonEntry["rid"] = nullptr; - - if (encodingMapping.ssrc != 0u) - jsonEntry["ssrc"] = encodingMapping.ssrc; - else - jsonEntry["ssrc"] = nullptr; - - jsonEntry["mappedSsrc"] = encodingMapping.mappedSsrc; - } + for (const auto& encodingMapping : this->rtpMapping.encodings) + { + encodings.emplace_back(FBS::RtpParameters::CreateEncodingMappingDirect( + builder, + encodingMapping.rid.c_str(), + encodingMapping.ssrc != 0u ? flatbuffers::Optional(encodingMapping.ssrc) + : flatbuffers::nullopt, + nullptr, /* capability mode. NOTE: Present in NODE*/ + encodingMapping.mappedSsrc)); } + // Build rtpMapping. + auto rtpMapping = FBS::RtpParameters::CreateRtpMappingDirect(builder, &codecs, &encodings); + // Add rtpStreams. - jsonObject["rtpStreams"] = json::array(); - auto jsonRtpStreamsIt = jsonObject.find("rtpStreams"); + std::vector> rtpStreams; - for (auto* rtpStream : this->rtpStreamByEncodingIdx) + for (const auto* rtpStream : this->rtpStreamByEncodingIdx) { if (!rtpStream) continue; - jsonRtpStreamsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonRtpStreamsIt)[jsonRtpStreamsIt->size() - 1]; - - rtpStream->FillJson(jsonEntry); + rtpStreams.emplace_back(rtpStream->FillBuffer(builder)); } - // Add paused. - jsonObject["paused"] = this->paused; - // Add traceEventTypes. - std::vector traceEventTypes; - std::ostringstream traceEventTypesStream; + std::vector> traceEventTypes; if (this->traceEventTypes.rtp) - traceEventTypes.emplace_back("rtp"); + traceEventTypes.emplace_back(builder.CreateString("rtp")); if (this->traceEventTypes.keyframe) - traceEventTypes.emplace_back("keyframe"); + traceEventTypes.emplace_back(builder.CreateString("keyframe")); if (this->traceEventTypes.nack) - traceEventTypes.emplace_back("nack"); + traceEventTypes.emplace_back(builder.CreateString("nack")); if (this->traceEventTypes.pli) - traceEventTypes.emplace_back("pli"); + traceEventTypes.emplace_back(builder.CreateString("pli")); if (this->traceEventTypes.fir) - traceEventTypes.emplace_back("fir"); - - if (!traceEventTypes.empty()) - { - std::copy( - traceEventTypes.begin(), - traceEventTypes.end() - 1, - std::ostream_iterator(traceEventTypesStream, ",")); - traceEventTypesStream << traceEventTypes.back(); - } - - jsonObject["traceEventTypes"] = traceEventTypesStream.str(); + traceEventTypes.emplace_back(builder.CreateString("fir")); + + return FBS::Producer::CreateDumpResponseDirect( + builder, + this->id.c_str(), + this->kind == RTC::Media::Kind::AUDIO ? FBS::RtpParameters::MediaKind::AUDIO + : FBS::RtpParameters::MediaKind::VIDEO, + RTC::RtpParameters::GetTypeString(this->type).c_str(), + rtpParameters, + rtpMapping, + &rtpStreams, + &traceEventTypes, + this->paused); } - void Producer::FillJsonStats(json& jsonArray) const + flatbuffers::Offset Producer::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); + std::vector> rtpStreams; + for (auto* rtpStream : this->rtpStreamByEncodingIdx) { if (!rtpStream) continue; - jsonArray.emplace_back(json::value_t::object); - - auto& jsonEntry = jsonArray[jsonArray.size() - 1]; - - rtpStream->FillJsonStats(jsonEntry); + rtpStreams.emplace_back(rtpStream->FillBufferStats(builder)); } + + return FBS::Producer::CreateGetStatsResponseDirect(builder, &rtpStreams); } void Producer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::PRODUCER_DUMP: + case Channel::ChannelRequest::Method::PRODUCER_DUMP: { - json data = json::object(); + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); - FillJson(data); - - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_Producer_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::PRODUCER_GET_STATS: + case Channel::ChannelRequest::Method::PRODUCER_GET_STATS: { - json data = json::array(); - - FillJsonStats(data); + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_Producer_GetStatsResponse, responseOffset); break; } - case Channel::ChannelRequest::MethodId::PRODUCER_PAUSE: + case Channel::ChannelRequest::Method::PRODUCER_PAUSE: { if (this->paused) { @@ -533,7 +386,7 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::PRODUCER_RESUME: + case Channel::ChannelRequest::Method::PRODUCER_RESUME: { if (!this->paused) { @@ -574,23 +427,16 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::PRODUCER_ENABLE_TRACE_EVENT: + case Channel::ChannelRequest::Method::PRODUCER_ENABLE_TRACE_EVENT: { - auto jsonTypesIt = request->data.find("types"); - - // Disable all if no entries. - if (jsonTypesIt == request->data.end() || !jsonTypesIt->is_array()) - MS_THROW_TYPE_ERROR("wrong types (not an array)"); + const auto* body = request->data->body_as(); // Reset traceEventTypes. struct TraceEventTypes newTraceEventTypes; - for (const auto& type : *jsonTypesIt) + for (const auto& type : *body->events()) { - if (!type.is_string()) - MS_THROW_TYPE_ERROR("wrong type (not a string)"); - - const std::string typeStr = type.get(); + const auto typeStr = type->str(); if (typeStr == "rtp") newTraceEventTypes.rtp = true; @@ -613,28 +459,28 @@ namespace RTC default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } } - void Producer::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) + void Producer::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); - switch (notification->eventId) + switch (notification->event) { - case PayloadChannel::PayloadChannelNotification::EventId::PRODUCER_SEND: + case Channel::ChannelNotification::Event::PRODUCER_SEND: { - const auto* data = notification->payload; - auto len = notification->payloadLen; + const auto* body = notification->data->body_as(); + auto len = body->data()->size(); // Increase receive transmission. this->listener->OnProducerReceiveData(this, len); if (len > RTC::MtuSize + 100) { - MS_WARN_TAG(rtp, "given RTP packet exceeds maximum size [len:%zu]", len); + MS_WARN_TAG(rtp, "given RTP packet exceeds maximum size [len:%i]", len); break; } @@ -644,7 +490,7 @@ namespace RTC Producer::buffer = new uint8_t[RTC::MtuSize + 100]; // Copy the received packet into this buffer so it can be expanded later. - std::memcpy(Producer::buffer, data, static_cast(len)); + std::memcpy(Producer::buffer, body->data()->data(), static_cast(len)); RTC::RtpPacket* packet = RTC::RtpPacket::Parse(Producer::buffer, len); @@ -663,7 +509,7 @@ namespace RTC default: { - MS_ERROR("unknown event '%s'", notification->event.c_str()); + MS_ERROR("unknown event '%s'", notification->eventCStr); } } } @@ -1503,13 +1349,17 @@ namespace RTC this->videoOrientation.flip = flip; this->videoOrientation.rotation = rotation; - json data = json::object(); - - data["camera"] = this->videoOrientation.camera; - data["flip"] = this->videoOrientation.flip; - data["rotation"] = this->videoOrientation.rotation; - - this->shared->channelNotifier->Emit(this->id, "videoorientationchange", data); + auto notification = FBS::Producer::CreateVideoOrientationChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), + this->videoOrientation.camera, + this->videoOrientation.flip, + this->videoOrientation.rotation); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::PRODUCER_VIDEO_ORIENTATION_CHANGE, + FBS::Notification::Body::FBS_Producer_VideoOrientationChangeNotification, + notification); } } } @@ -1519,27 +1369,28 @@ namespace RTC { MS_TRACE(); - json data = json::array(); + std::vector> scores; - for (auto* rtpStream : this->rtpStreamByEncodingIdx) + for (const auto* rtpStream : this->rtpStreamByEncodingIdx) { if (!rtpStream) continue; - data.emplace_back(json::value_t::object); - - auto& jsonEntry = data[data.size() - 1]; - - jsonEntry["encodingIdx"] = rtpStream->GetEncodingIdx(); - jsonEntry["ssrc"] = rtpStream->GetSsrc(); - - if (!rtpStream->GetRid().empty()) - jsonEntry["rid"] = rtpStream->GetRid(); - - jsonEntry["score"] = rtpStream->GetScore(); + scores.emplace_back(FBS::Producer::CreateScoreDirect( + this->shared->channelNotifier->GetBufferBuilder(), + rtpStream->GetSsrc(), + !rtpStream->GetRid().empty() ? rtpStream->GetRid().c_str() : nullptr, + rtpStream->GetScore())); } - this->shared->channelNotifier->Emit(this->id, "score", data); + auto notification = FBS::Producer::CreateScoreNotificationDirect( + this->shared->channelNotifier->GetBufferBuilder(), &scores); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::PRODUCER_SCORE, + FBS::Notification::Body::FBS_Producer_ScoreNotification, + notification); } inline void Producer::EmitTraceEventRtpAndKeyFrameTypes(RTC::RtpPacket* packet, bool isRtx) const @@ -1548,33 +1399,33 @@ namespace RTC if (this->traceEventTypes.keyframe && packet->IsKeyFrame()) { - json data = json::object(); - - data["type"] = "keyframe"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "in"; - - packet->FillJson(data["info"]); - - if (isRtx) - data["info"]["isRtx"] = true; - - this->shared->channelNotifier->Emit(this->id, "trace", data); + auto traceInfo = FBS::Producer::CreateKeyFrameTraceInfo( + this->shared->channelNotifier->GetBufferBuilder(), isRtx); + + auto notification = FBS::Producer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Producer::TraceType::KEYFRAME, + DepLibUV::GetTimeMs(), + FBS::Producer::TraceDirection::DIRECTION_IN, + FBS::Producer::TraceInfo::KeyFrameTraceInfo, + traceInfo.Union()); + + EmitTraceEvent(notification); } else if (this->traceEventTypes.rtp) { - json data = json::object(); - - data["type"] = "rtp"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "in"; - - packet->FillJson(data["info"]); - - if (isRtx) - data["info"]["isRtx"] = true; - - this->shared->channelNotifier->Emit(this->id, "trace", data); + auto traceInfo = + FBS::Producer::CreateRtpTraceInfo(this->shared->channelNotifier->GetBufferBuilder(), isRtx); + + auto notification = FBS::Producer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Producer::TraceType::RTP, + DepLibUV::GetTimeMs(), + FBS::Producer::TraceDirection::DIRECTION_IN, + FBS::Producer::TraceInfo::RtpTraceInfo, + traceInfo.Union()); + + EmitTraceEvent(notification); } } @@ -1585,14 +1436,18 @@ namespace RTC if (!this->traceEventTypes.pli) return; - json data = json::object(); + auto traceInfo = + FBS::Producer::CreatePliTraceInfo(this->shared->channelNotifier->GetBufferBuilder(), ssrc); - data["type"] = "pli"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "out"; - data["info"]["ssrc"] = ssrc; + auto notification = FBS::Producer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Producer::TraceType::PLI, + DepLibUV::GetTimeMs(), + FBS::Producer::TraceDirection::DIRECTION_OUT, + FBS::Producer::TraceInfo::PliTraceInfo, + traceInfo.Union()); - this->shared->channelNotifier->Emit(this->id, "trace", data); + EmitTraceEvent(notification); } inline void Producer::EmitTraceEventFirType(uint32_t ssrc) const @@ -1602,14 +1457,18 @@ namespace RTC if (!this->traceEventTypes.fir) return; - json data = json::object(); + auto traceInfo = + FBS::Producer::CreateFirTraceInfo(this->shared->channelNotifier->GetBufferBuilder(), ssrc); - data["type"] = "fir"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "out"; - data["info"]["ssrc"] = ssrc; + auto notification = FBS::Producer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Producer::TraceType::FIR, + DepLibUV::GetTimeMs(), + FBS::Producer::TraceDirection::DIRECTION_OUT, + FBS::Producer::TraceInfo::FirTraceInfo, + traceInfo.Union()); - this->shared->channelNotifier->Emit(this->id, "trace", data); + EmitTraceEvent(notification); } inline void Producer::EmitTraceEventNackType() const @@ -1619,14 +1478,25 @@ namespace RTC if (!this->traceEventTypes.nack) return; - json data = json::object(); + auto notification = FBS::Producer::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Producer::TraceType::NACK, + DepLibUV::GetTimeMs(), + FBS::Producer::TraceDirection::DIRECTION_OUT); - data["type"] = "nack"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "out"; - data["info"] = json::object(); + EmitTraceEvent(notification); + } - this->shared->channelNotifier->Emit(this->id, "trace", data); + inline void Producer::EmitTraceEvent( + flatbuffers::Offset& notification) const + { + MS_TRACE(); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::PRODUCER_TRACE, + FBS::Notification::Body::FBS_Producer_TraceNotification, + notification); } inline void Producer::OnRtpStreamScore(RTC::RtpStream* rtpStream, uint8_t score, uint8_t previousScore) diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index b56dc1c345..92b7bfacde 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -25,8 +25,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*ChannelNotificationHandler*/ nullptr); } Router::~Router() @@ -63,227 +62,198 @@ namespace RTC this->mapDataProducers.clear(); } - void Router::FillJson(json& jsonObject) const + flatbuffers::Offset Router::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add id. - jsonObject["id"] = this->id; - // Add transportIds. - jsonObject["transportIds"] = json::array(); - auto jsonTransportIdsIt = jsonObject.find("transportIds"); + std::vector> transportIds; + transportIds.reserve(this->mapTransports.size()); for (const auto& kv : this->mapTransports) { const auto& transportId = kv.first; - jsonTransportIdsIt->emplace_back(transportId); + transportIds.push_back(builder.CreateString(transportId)); } // Add rtpObserverIds. - jsonObject["rtpObserverIds"] = json::array(); - auto jsonRtpObserverIdsIt = jsonObject.find("rtpObserverIds"); + std::vector> rtpObserverIds; + rtpObserverIds.reserve(this->mapRtpObservers.size()); for (const auto& kv : this->mapRtpObservers) { const auto& rtpObserverId = kv.first; - jsonRtpObserverIdsIt->emplace_back(rtpObserverId); + rtpObserverIds.push_back(builder.CreateString(rtpObserverId)); } // Add mapProducerIdConsumerIds. - jsonObject["mapProducerIdConsumerIds"] = json::object(); - auto jsonMapProducerConsumersIt = jsonObject.find("mapProducerIdConsumerIds"); + std::vector> mapProducerIdConsumerIds; + mapProducerIdConsumerIds.reserve(this->mapProducerConsumers.size()); for (const auto& kv : this->mapProducerConsumers) { auto* producer = kv.first; const auto& consumers = kv.second; - (*jsonMapProducerConsumersIt)[producer->id] = json::array(); - auto jsonProducerIdIt = jsonMapProducerConsumersIt->find(producer->id); + std::vector> consumerIds; + consumerIds.reserve(consumers.size()); for (auto* consumer : consumers) { - jsonProducerIdIt->emplace_back(consumer->id); + consumerIds.emplace_back(builder.CreateString(consumer->id)); } + + mapProducerIdConsumerIds.emplace_back( + FBS::Common::CreateStringStringArrayDirect(builder, producer->id.c_str(), &consumerIds)); } // Add mapConsumerIdProducerId. - jsonObject["mapConsumerIdProducerId"] = json::object(); - auto jsonMapConsumerProducerIt = jsonObject.find("mapConsumerIdProducerId"); + std::vector> mapConsumerIdProducerId; + mapConsumerIdProducerId.reserve(this->mapConsumerProducer.size()); for (const auto& kv : this->mapConsumerProducer) { auto* consumer = kv.first; auto* producer = kv.second; - (*jsonMapConsumerProducerIt)[consumer->id] = producer->id; + mapConsumerIdProducerId.emplace_back( + FBS::Common::CreateStringStringDirect(builder, consumer->id.c_str(), producer->id.c_str())); } // Add mapProducerIdObserverIds. - jsonObject["mapProducerIdObserverIds"] = json::object(); - auto jsonMapProducerRtpObserversIt = jsonObject.find("mapProducerIdObserverIds"); + std::vector> mapProducerIdObserverIds; + mapProducerIdObserverIds.reserve(this->mapProducerRtpObservers.size()); for (const auto& kv : this->mapProducerRtpObservers) { auto* producer = kv.first; const auto& rtpObservers = kv.second; - (*jsonMapProducerRtpObserversIt)[producer->id] = json::array(); - auto jsonProducerIdIt = jsonMapProducerRtpObserversIt->find(producer->id); + std::vector> observerIds; + observerIds.reserve(rtpObservers.size()); for (auto* rtpObserver : rtpObservers) { - jsonProducerIdIt->emplace_back(rtpObserver->id); + observerIds.emplace_back(builder.CreateString(rtpObserver->id)); } + + mapProducerIdObserverIds.emplace_back( + FBS::Common::CreateStringStringArrayDirect(builder, producer->id.c_str(), &observerIds)); } // Add mapDataProducerIdDataConsumerIds. - jsonObject["mapDataProducerIdDataConsumerIds"] = json::object(); - auto jsonMapDataProducerDataConsumersIt = jsonObject.find("mapDataProducerIdDataConsumerIds"); + std::vector> mapDataProducerIdDataConsumerIds; + mapDataProducerIdDataConsumerIds.reserve(this->mapDataProducerDataConsumers.size()); for (const auto& kv : this->mapDataProducerDataConsumers) { auto* dataProducer = kv.first; const auto& dataConsumers = kv.second; - (*jsonMapDataProducerDataConsumersIt)[dataProducer->id] = json::array(); - auto jsonDataProducerIdIt = jsonMapDataProducerDataConsumersIt->find(dataProducer->id); + std::vector> dataConsumerIds; + dataConsumerIds.reserve(dataConsumers.size()); for (auto* dataConsumer : dataConsumers) { - jsonDataProducerIdIt->emplace_back(dataConsumer->id); + dataConsumerIds.emplace_back(builder.CreateString(dataConsumer->id)); } + + mapDataProducerIdDataConsumerIds.emplace_back(FBS::Common::CreateStringStringArrayDirect( + builder, dataProducer->id.c_str(), &dataConsumerIds)); } // Add mapDataConsumerIdDataProducerId. - jsonObject["mapDataConsumerIdDataProducerId"] = json::object(); - auto jsonMapDataConsumerDataProducerIt = jsonObject.find("mapDataConsumerIdDataProducerId"); + std::vector> mapDataConsumerIdDataProducerId; + mapDataConsumerIdDataProducerId.reserve(this->mapDataConsumerDataProducer.size()); for (const auto& kv : this->mapDataConsumerDataProducer) { auto* dataConsumer = kv.first; auto* dataProducer = kv.second; - (*jsonMapDataConsumerDataProducerIt)[dataConsumer->id] = dataProducer->id; + mapDataConsumerIdDataProducerId.emplace_back(FBS::Common::CreateStringStringDirect( + builder, dataConsumer->id.c_str(), dataProducer->id.c_str())); } + + return FBS::Router::CreateDumpResponseDirect( + builder, + this->id.c_str(), + &transportIds, + &rtpObserverIds, + &mapProducerIdConsumerIds, + &mapConsumerIdProducerId, + &mapProducerIdObserverIds, + &mapDataProducerIdDataConsumerIds, + &mapDataConsumerIdDataProducerId); } void Router::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::ROUTER_DUMP: + case Channel::ChannelRequest::Method::ROUTER_DUMP: { - json data = json::object(); + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); - FillJson(data); - - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_Router_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT: + case Channel::ChannelRequest::Method::ROUTER_CREATE_WEBRTC_TRANSPORT: { - std::string transportId; + const auto* body = request->data->body_as(); + + auto transportId = body->transportId()->str(); // This may throw. - SetNewTransportIdFromData(request->data, transportId); + CheckNoTransport(transportId); // This may throw. auto* webRtcTransport = - new RTC::WebRtcTransport(this->shared, transportId, this, request->data); + new RTC::WebRtcTransport(this->shared, transportId, this, body->options()); // Insert into the map. this->mapTransports[transportId] = webRtcTransport; MS_DEBUG_DEV("WebRtcTransport created [transportId:%s]", transportId.c_str()); - json data = json::object(); - - webRtcTransport->FillJson(data); + auto dumpOffset = webRtcTransport->FillBuffer(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_WebRtcTransport_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT_WITH_SERVER: + case Channel::ChannelRequest::Method::ROUTER_CREATE_WEBRTC_TRANSPORT_WITH_SERVER: { - std::string transportId; + const auto* body = request->data->body_as(); + auto transportId = body->transportId()->str(); // This may throw. - SetNewTransportIdFromData(request->data, transportId); + CheckNoTransport(transportId); - auto jsonWebRtcServerIdIt = request->data.find("webRtcServerId"); + const auto* options = body->options(); + const auto* listenInfo = options->listen_as(); - if (jsonWebRtcServerIdIt == request->data.end() || !jsonWebRtcServerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing webRtcServerId"); - } - - std::string webRtcServerId = jsonWebRtcServerIdIt->get(); + auto webRtcServerId = listenInfo->webRtcServerId()->str(); auto* webRtcServer = this->listener->OnRouterNeedWebRtcServer(this, webRtcServerId); if (!webRtcServer) MS_THROW_ERROR("wrong webRtcServerId (no associated WebRtcServer found)"); - bool enableUdp{ true }; - auto jsonEnableUdpIt = request->data.find("enableUdp"); - - if (jsonEnableUdpIt != request->data.end()) - { - if (!jsonEnableUdpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong enableUdp (not a boolean)"); - - enableUdp = jsonEnableUdpIt->get(); - } - - bool enableTcp{ false }; - auto jsonEnableTcpIt = request->data.find("enableTcp"); - - if (jsonEnableTcpIt != request->data.end()) - { - if (!jsonEnableTcpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong enableTcp (not a boolean)"); - - enableTcp = jsonEnableTcpIt->get(); - } - - bool preferUdp{ false }; - auto jsonPreferUdpIt = request->data.find("preferUdp"); - - if (jsonPreferUdpIt != request->data.end()) - { - if (!jsonPreferUdpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong preferUdp (not a boolean)"); - - preferUdp = jsonPreferUdpIt->get(); - } - - bool preferTcp{ false }; - auto jsonPreferTcpIt = request->data.find("preferTcp"); - - if (jsonPreferTcpIt != request->data.end()) - { - if (!jsonPreferTcpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong preferTcp (not a boolean)"); - - preferTcp = jsonPreferTcpIt->get(); - } - - auto iceCandidates = - webRtcServer->GetIceCandidates(enableUdp, enableTcp, preferUdp, preferTcp); + auto iceCandidates = webRtcServer->GetIceCandidates( + options->enableUdp(), options->enableTcp(), options->preferUdp(), options->preferTcp()); // This may throw. auto* webRtcTransport = new RTC::WebRtcTransport( - this->shared, transportId, this, webRtcServer, iceCandidates, request->data); + this->shared, transportId, this, webRtcServer, iceCandidates, options); // Insert into the map. this->mapTransports[transportId] = webRtcTransport; @@ -291,95 +261,92 @@ namespace RTC MS_DEBUG_DEV( "WebRtcTransport with WebRtcServer created [transportId:%s]", transportId.c_str()); - json data = json::object(); + auto dumpOffset = webRtcTransport->FillBuffer(request->GetBufferBuilder()); - webRtcTransport->FillJson(data); - - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_WebRtcTransport_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::ROUTER_CREATE_PLAIN_TRANSPORT: + case Channel::ChannelRequest::Method::ROUTER_CREATE_PLAIN_TRANSPORT: { - std::string transportId; + const auto* body = request->data->body_as(); + auto transportId = body->transportId()->str(); - // This may throw - SetNewTransportIdFromData(request->data, transportId); + // This may throw. + CheckNoTransport(transportId); auto* plainTransport = - new RTC::PlainTransport(this->shared, transportId, this, request->data); + new RTC::PlainTransport(this->shared, transportId, this, body->options()); // Insert into the map. this->mapTransports[transportId] = plainTransport; MS_DEBUG_DEV("PlainTransport created [transportId:%s]", transportId.c_str()); - json data = json::object(); + auto dumpOffset = plainTransport->FillBuffer(request->GetBufferBuilder()); - plainTransport->FillJson(data); - - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_PlainTransport_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::ROUTER_CREATE_PIPE_TRANSPORT: + case Channel::ChannelRequest::Method::ROUTER_CREATE_PIPE_TRANSPORT: { - std::string transportId; + const auto* body = request->data->body_as(); + auto transportId = body->transportId()->str(); - // This may throw - SetNewTransportIdFromData(request->data, transportId); + // This may throw. + CheckNoTransport(transportId); - auto* pipeTransport = new RTC::PipeTransport(this->shared, transportId, this, request->data); + auto* pipeTransport = + new RTC::PipeTransport(this->shared, transportId, this, body->options()); // Insert into the map. this->mapTransports[transportId] = pipeTransport; MS_DEBUG_DEV("PipeTransport created [transportId:%s]", transportId.c_str()); - json data = json::object(); + auto dumpOffset = pipeTransport->FillBuffer(request->GetBufferBuilder()); - pipeTransport->FillJson(data); - - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_PipeTransport_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::ROUTER_CREATE_DIRECT_TRANSPORT: + case Channel::ChannelRequest::Method::ROUTER_CREATE_DIRECT_TRANSPORT: { - std::string transportId; + const auto* body = request->data->body_as(); + auto transportId = body->transportId()->str(); - // This may throw - SetNewTransportIdFromData(request->data, transportId); + // This may throw. + CheckNoTransport(transportId); auto* directTransport = - new RTC::DirectTransport(this->shared, transportId, this, request->data); + new RTC::DirectTransport(this->shared, transportId, this, body->options()); // Insert into the map. this->mapTransports[transportId] = directTransport; MS_DEBUG_DEV("DirectTransport created [transportId:%s]", transportId.c_str()); - json data = json::object(); + auto dumpOffset = directTransport->FillBuffer(request->GetBufferBuilder()); - directTransport->FillJson(data); - - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_DirectTransport_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::ROUTER_CREATE_ACTIVE_SPEAKER_OBSERVER: + case Channel::ChannelRequest::Method::ROUTER_CREATE_ACTIVE_SPEAKER_OBSERVER: { - std::string rtpObserverId; + const auto* body = request->data->body_as(); + auto rtpObserverId = body->activeSpeakerObserverId()->str(); // This may throw. - SetNewRtpObserverIdFromData(request->data, rtpObserverId); + CheckNoRtpObserver(rtpObserverId); auto* activeSpeakerObserver = - new RTC::ActiveSpeakerObserver(this->shared, rtpObserverId, this, request->data); + new RTC::ActiveSpeakerObserver(this->shared, rtpObserverId, this, body->options()); // Insert into the map. this->mapRtpObservers[rtpObserverId] = activeSpeakerObserver; @@ -391,15 +358,16 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::ROUTER_CREATE_AUDIO_LEVEL_OBSERVER: + case Channel::ChannelRequest::Method::ROUTER_CREATE_AUDIO_LEVEL_OBSERVER: { - std::string rtpObserverId; + const auto* body = request->data->body_as(); + auto rtpObserverId = body->rtpObserverId()->str(); - // This may throw - SetNewRtpObserverIdFromData(request->data, rtpObserverId); + // This may throw. + CheckNoRtpObserver(rtpObserverId); auto* audioLevelObserver = - new RTC::AudioLevelObserver(this->shared, rtpObserverId, this, request->data); + new RTC::AudioLevelObserver(this->shared, rtpObserverId, this, body->options()); // Insert into the map. this->mapRtpObservers[rtpObserverId] = audioLevelObserver; @@ -411,10 +379,13 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::ROUTER_CLOSE_TRANSPORT: + case Channel::ChannelRequest::Method::ROUTER_CLOSE_TRANSPORT: { + const auto* body = request->data->body_as(); + auto transportId = body->transportId()->str(); + // This may throw. - RTC::Transport* transport = GetTransportFromData(request->data); + RTC::Transport* transport = GetTransportById(transportId); // Tell the Transport to close all its Producers and Consumers so it will // notify us about their closures. @@ -433,10 +404,13 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::ROUTER_CLOSE_RTP_OBSERVER: + case Channel::ChannelRequest::Method::ROUTER_CLOSE_RTP_OBSERVER: { + const auto* body = request->data->body_as(); + auto rtpObserverId = body->rtpObserverId()->str(); + // This may throw. - RTC::RtpObserver* rtpObserver = GetRtpObserverFromData(request->data); + RTC::RtpObserver* rtpObserver = GetRtpObserverById(rtpObserverId); // Remove it from the map. this->mapRtpObservers.erase(rtpObserver->id); @@ -461,89 +435,45 @@ namespace RTC default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", Channel::ChannelRequest::method2String[request->method]); } } } - void Router::SetNewTransportIdFromData(json& data, std::string& transportId) const + void Router::CheckNoTransport(const std::string& transportId) const { - MS_TRACE(); - - auto jsonTransportIdIt = data.find("transportId"); - - if (jsonTransportIdIt == data.end() || !jsonTransportIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing transportId"); - } - - transportId.assign(jsonTransportIdIt->get()); - if (this->mapTransports.find(transportId) != this->mapTransports.end()) - { - MS_THROW_ERROR("a Transport with same transportId already exists"); - } + MS_THROW_ERROR("a Transport with same id already exists"); } - RTC::Transport* Router::GetTransportFromData(json& data) const + void Router::CheckNoRtpObserver(const std::string& rtpObserverId) const { - MS_TRACE(); - - auto jsonTransportIdIt = data.find("transportId"); - - if (jsonTransportIdIt == data.end() || !jsonTransportIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing transportId"); - } - - auto it = this->mapTransports.find(jsonTransportIdIt->get()); - - if (it == this->mapTransports.end()) - MS_THROW_ERROR("Transport not found"); - - RTC::Transport* transport = it->second; - - return transport; + if (this->mapRtpObservers.find(rtpObserverId) != this->mapRtpObservers.end()) + MS_THROW_ERROR("an RtpObserver with same id already exists"); } - void Router::SetNewRtpObserverIdFromData(json& data, std::string& rtpObserverId) const + RTC::Transport* Router::GetTransportById(const std::string& transportId) const { MS_TRACE(); - auto jsonRtpObserverIdIt = data.find("rtpObserverId"); - - if (jsonRtpObserverIdIt == data.end() || !jsonRtpObserverIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing rtpObserverId"); - } + auto it = this->mapTransports.find(transportId); - rtpObserverId.assign(jsonRtpObserverIdIt->get()); + if (this->mapTransports.find(transportId) == this->mapTransports.end()) + MS_THROW_ERROR("Transport not found"); - if (this->mapRtpObservers.find(rtpObserverId) != this->mapRtpObservers.end()) - { - MS_THROW_ERROR("an RtpObserver with same rtpObserverId already exists"); - } + return it->second; } - RTC::RtpObserver* Router::GetRtpObserverFromData(json& data) const + RTC::RtpObserver* Router::GetRtpObserverById(const std::string& rtpObserverId) const { MS_TRACE(); - auto jsonRtpObserverIdIt = data.find("rtpObserverId"); + auto it = this->mapRtpObservers.find(rtpObserverId); - if (jsonRtpObserverIdIt == data.end() || !jsonRtpObserverIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing rtpObserverId"); - } - - auto it = this->mapRtpObservers.find(jsonRtpObserverIdIt->get()); - - if (it == this->mapRtpObservers.end()) + if (this->mapRtpObservers.find(rtpObserverId) == this->mapRtpObservers.end()) MS_THROW_ERROR("RtpObserver not found"); - RTC::RtpObserver* rtpObserver = it->second; - - return rtpObserver; + return it->second; } inline void Router::OnTransportNewProducer(RTC::Transport* /*transport*/, RTC::Producer* producer) @@ -759,7 +689,7 @@ namespace RTC } inline void Router::OnTransportNewConsumer( - RTC::Transport* /*transport*/, RTC::Consumer* consumer, std::string& producerId) + RTC::Transport* /*transport*/, RTC::Consumer* consumer, const std::string& producerId) { MS_TRACE(); diff --git a/worker/src/RTC/RtpDictionaries/Parameters.cpp b/worker/src/RTC/RtpDictionaries/Parameters.cpp index c51b8c9b9f..ab3ee0b776 100644 --- a/worker/src/RTC/RtpDictionaries/Parameters.cpp +++ b/worker/src/RTC/RtpDictionaries/Parameters.cpp @@ -8,104 +8,121 @@ namespace RTC { /* Instance methods. */ - void Parameters::FillJson(json& jsonObject) const + std::vector> Parameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Force it to be an object even if no key/values are added below. - jsonObject = json::object(); + std::vector> parameters; - for (auto& kv : this->mapKeyValues) + for (const auto& kv : this->mapKeyValues) { - auto& key = kv.first; - auto& value = kv.second; + const auto& key = kv.first; + const auto& value = kv.second; + + flatbuffers::Offset parameter; switch (value.type) { case Value::Type::BOOLEAN: - jsonObject[key] = value.booleanValue; + { + auto valueOffset = FBS::RtpParameters::CreateBoolean(builder, value.booleanValue); + + parameter = FBS::RtpParameters::CreateParameterDirect( + builder, key.c_str(), FBS::RtpParameters::Value::Boolean, valueOffset.Union()); + break; + } case Value::Type::INTEGER: - jsonObject[key] = value.integerValue; + { + auto valueOffset = FBS::RtpParameters::CreateInteger(builder, value.integerValue); + + parameters.emplace_back(FBS::RtpParameters::CreateParameterDirect( + builder, key.c_str(), FBS::RtpParameters::Value::Integer, valueOffset.Union())); + break; + } case Value::Type::DOUBLE: - jsonObject[key] = value.doubleValue; + { + auto valueOffset = FBS::RtpParameters::CreateDouble(builder, value.doubleValue); + + parameters.emplace_back(FBS::RtpParameters::CreateParameterDirect( + builder, key.c_str(), FBS::RtpParameters::Value::Double, valueOffset.Union())); + break; + } case Value::Type::STRING: - jsonObject[key] = value.stringValue; + { + auto valueOffset = + FBS::RtpParameters::CreateStringDirect(builder, value.stringValue.c_str()); + + parameters.emplace_back(FBS::RtpParameters::CreateParameterDirect( + builder, key.c_str(), FBS::RtpParameters::Value::String, valueOffset.Union())); + break; + } case Value::Type::ARRAY_OF_INTEGERS: - jsonObject[key] = value.arrayOfIntegers; + { + auto valueOffset = + FBS::RtpParameters::CreateIntegerArrayDirect(builder, &value.arrayOfIntegers); + + parameters.emplace_back(FBS::RtpParameters::CreateParameterDirect( + builder, key.c_str(), FBS::RtpParameters::Value::IntegerArray, valueOffset.Union())); + break; + } } } + + return parameters; } - void Parameters::Set(json& data) + void Parameters::Set(const flatbuffers::Vector>* data) { MS_TRACE(); - MS_ASSERT(data.is_object(), "data is not an object"); - - for (json::iterator it = data.begin(); it != data.end(); ++it) + for (const auto* parameter : *data) { - const std::string& key = it.key(); - auto& value = it.value(); + const auto key = parameter->name()->str(); - switch (value.type()) + switch (parameter->value_type()) { - case json::value_t::boolean: + case FBS::RtpParameters::Value::Boolean: { - this->mapKeyValues.emplace(key, Value(value.get())); + this->mapKeyValues.emplace( + key, Value((parameter->value_as_Boolean()->value() == 0) ? false : true)); break; } - case json::value_t::number_integer: - case json::value_t::number_unsigned: + case FBS::RtpParameters::Value::Integer: { - this->mapKeyValues.emplace(key, Value(value.get())); + this->mapKeyValues.emplace(key, Value(parameter->value_as_Integer()->value())); break; } - case json::value_t::number_float: + case FBS::RtpParameters::Value::Double: { - this->mapKeyValues.emplace(key, Value(value.get())); + this->mapKeyValues.emplace(key, Value(parameter->value_as_Double()->value())); break; } - case json::value_t::string: + case FBS::RtpParameters::Value::String: { - this->mapKeyValues.emplace(key, Value(value.get())); + this->mapKeyValues.emplace(key, Value(parameter->value_as_String()->value()->str())); break; } - case json::value_t::array: + case FBS::RtpParameters::Value::IntegerArray: { - std::vector arrayOfIntegers; - bool isValid = true; - - for (auto& entry : value) - { - if (!entry.is_number_integer()) - { - isValid = false; - - break; - } - - arrayOfIntegers.emplace_back(entry.get()); - } - - if (!arrayOfIntegers.empty() && isValid) - this->mapKeyValues.emplace(key, Value(arrayOfIntegers)); + this->mapKeyValues.emplace(key, Value(parameter->value_as_IntegerArray()->value())); break; } @@ -124,7 +141,7 @@ namespace RTC if (it == this->mapKeyValues.end()) return false; - auto& value = it->second; + const auto& value = it->second; return value.type == Value::Type::BOOLEAN; } @@ -138,7 +155,7 @@ namespace RTC if (it == this->mapKeyValues.end()) return false; - auto& value = it->second; + const auto& value = it->second; return value.type == Value::Type::INTEGER; } @@ -152,7 +169,7 @@ namespace RTC if (it == this->mapKeyValues.end()) return false; - auto& value = it->second; + const auto& value = it->second; return value.type == Value::Type::INTEGER && value.integerValue >= 0; } @@ -166,7 +183,7 @@ namespace RTC if (it == this->mapKeyValues.end()) return false; - auto& value = it->second; + const auto& value = it->second; return value.type == Value::Type::DOUBLE; } @@ -180,7 +197,7 @@ namespace RTC if (it == this->mapKeyValues.end()) return false; - auto& value = it->second; + const auto& value = it->second; return value.type == Value::Type::STRING; } @@ -194,7 +211,7 @@ namespace RTC if (it == this->mapKeyValues.end()) return false; - auto& value = it->second; + const auto& value = it->second; return value.type == Value::Type::ARRAY_OF_INTEGERS; } @@ -208,8 +225,8 @@ namespace RTC if (it == this->mapKeyValues.end()) return false; - auto& value = it->second; - auto& array = value.arrayOfIntegers; + const auto& value = it->second; + const auto& array = value.arrayOfIntegers; return std::find(array.begin(), array.end(), integer) != array.end(); } @@ -222,7 +239,7 @@ namespace RTC MS_ASSERT(it != this->mapKeyValues.end(), "key does not exist [key:%s]", key.c_str()); - auto& value = it->second; + const auto& value = it->second; return value.booleanValue; } @@ -235,7 +252,7 @@ namespace RTC MS_ASSERT(it != this->mapKeyValues.end(), "key does not exist [key:%s]", key.c_str()); - auto& value = it->second; + const auto& value = it->second; return value.integerValue; } @@ -248,7 +265,7 @@ namespace RTC MS_ASSERT(it != this->mapKeyValues.end(), "key does not exist [key:%s]", key.c_str()); - auto& value = it->second; + const auto& value = it->second; return value.doubleValue; } @@ -261,7 +278,7 @@ namespace RTC MS_ASSERT(it != this->mapKeyValues.end(), "key does not exist [key:%s]", key.c_str()); - auto& value = it->second; + const auto& value = it->second; return value.stringValue; } @@ -274,7 +291,7 @@ namespace RTC MS_ASSERT(it != this->mapKeyValues.end(), "key does not exist [key:%s]", key.c_str()); - auto& value = it->second; + const auto& value = it->second; return value.arrayOfIntegers; } diff --git a/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp b/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp index 4c0f90f054..40a27c5614 100644 --- a/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp +++ b/worker/src/RTC/RtpDictionaries/RtcpFeedback.cpp @@ -9,36 +9,23 @@ namespace RTC { /* Instance methods. */ - RtcpFeedback::RtcpFeedback(json& data) + RtcpFeedback::RtcpFeedback(const FBS::RtpParameters::RtcpFeedback* data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonTypeIt = data.find("type"); - auto jsonParameterIt = data.find("parameter"); - - // type is mandatory. - if (jsonTypeIt == data.end() || !jsonTypeIt->is_string()) - MS_THROW_TYPE_ERROR("missing type"); - - this->type = jsonTypeIt->get(); + this->type = data->type()->str(); // parameter is optional. - if (jsonParameterIt != data.end() && jsonParameterIt->is_string()) - this->parameter = jsonParameterIt->get(); + if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtcpFeedback::VT_PARAMETER)) + this->parameter = data->parameter()->str(); } - void RtcpFeedback::FillJson(json& jsonObject) const + flatbuffers::Offset RtcpFeedback::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add type. - jsonObject["type"] = this->type; - - // Add parameter (optional). - if (this->parameter.length() > 0) - jsonObject["parameter"] = this->parameter; + return FBS::RtpParameters::CreateRtcpFeedbackDirect( + builder, this->type.c_str(), this->parameter.length() > 0 ? this->parameter.c_str() : nullptr); } } // namespace RTC diff --git a/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp b/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp index fe77eeebd1..c98713a9f9 100644 --- a/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp @@ -10,50 +10,24 @@ namespace RTC { /* Instance methods. */ - RtcpParameters::RtcpParameters(json& data) + RtcpParameters::RtcpParameters(const FBS::RtpParameters::RtcpParameters* data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonCnameIt = data.find("cname"); - auto jsonSsrcIt = data.find("ssrc"); - auto jsonRedicedSizeIt = data.find("reducedSize"); - // cname is optional. - if (jsonCnameIt != data.end() && jsonCnameIt->is_string()) - this->cname = jsonCnameIt->get(); - - // ssrc is optional. - // clang-format off - if ( - jsonSsrcIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonSsrcIt) - ) - // clang-format on - { - this->ssrc = jsonSsrcIt->get(); - } + if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtcpParameters::VT_CNAME)) + this->cname = data->cname()->str(); - // reducedSize is optional. - if (jsonRedicedSizeIt != data.end() && jsonRedicedSizeIt->is_boolean()) - this->reducedSize = jsonRedicedSizeIt->get(); + // reducedSize is optional, default value is true. + this->reducedSize = data->reducedSize(); } - void RtcpParameters::FillJson(json& jsonObject) const + flatbuffers::Offset RtcpParameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add cname. - if (!this->cname.empty()) - jsonObject["cname"] = this->cname; - - // Add ssrc. - if (this->ssrc != 0u) - jsonObject["ssrc"] = this->ssrc; - - // Add reducedSize. - jsonObject["reducedSize"] = this->reducedSize; + return FBS::RtpParameters::CreateRtcpParametersDirect( + builder, this->cname.c_str(), this->reducedSize); } } // namespace RTC diff --git a/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp index caab4b63ce..92655338ef 100644 --- a/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp @@ -10,77 +10,37 @@ namespace RTC { /* Instance methods. */ - RtpCodecParameters::RtpCodecParameters(json& data) + RtpCodecParameters::RtpCodecParameters(const FBS::RtpParameters::RtpCodecParameters* data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonMimeTypeIt = data.find("mimeType"); - auto jsonPayloadTypeIt = data.find("payloadType"); - auto jsonClockRateIt = data.find("clockRate"); - auto jsonChannelsIt = data.find("channels"); - auto jsonParametersIt = data.find("parameters"); - auto jsonRtcpFeedbackIt = data.find("rtcpFeedback"); - - // mimeType is mandatory. - if (jsonMimeTypeIt == data.end() || !jsonMimeTypeIt->is_string()) - MS_THROW_TYPE_ERROR("missing mimeType"); - // Set MIME field. // This may throw. - this->mimeType.SetMimeType(jsonMimeTypeIt->get()); - - // payloadType is mandatory. - // clang-format off - if ( - jsonPayloadTypeIt == data.end() || - !Utils::Json::IsPositiveInteger(*jsonPayloadTypeIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing payloadType"); - } - - this->payloadType = jsonPayloadTypeIt->get(); + this->mimeType.SetMimeType(data->mimeType()->str()); - // clockRate is mandatory. - // clang-format off - if ( - jsonClockRateIt == data.end() || - !Utils::Json::IsPositiveInteger(*jsonClockRateIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing clockRate"); - } + // payloadType. + this->payloadType = data->payloadType(); - this->clockRate = jsonClockRateIt->get(); + // clockRate. + this->clockRate = data->clockRate(); // channels is optional. - // clang-format off - if ( - jsonChannelsIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonChannelsIt) - ) - // clang-format on + if (data->channels().has_value()) { - this->channels = jsonChannelsIt->get(); + this->channels = data->channels().value(); } // parameters is optional. - if (jsonParametersIt != data.end() && jsonParametersIt->is_object()) - this->parameters.Set(*jsonParametersIt); + if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtpCodecParameters::VT_PARAMETERS)) + this->parameters.Set(data->parameters()); // rtcpFeedback is optional. - if (jsonRtcpFeedbackIt != data.end() && jsonRtcpFeedbackIt->is_array()) + if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtpCodecParameters::VT_RTCPFEEDBACK)) { - this->rtcpFeedback.reserve(jsonRtcpFeedbackIt->size()); + this->rtcpFeedback.reserve(data->rtcpFeedback()->size()); - for (auto& entry : *jsonRtcpFeedbackIt) + for (const auto* entry : *data->rtcpFeedback()) { - // This may throw due the constructor of RTC::RtcpFeedback. this->rtcpFeedback.emplace_back(entry); } } @@ -89,39 +49,29 @@ namespace RTC CheckCodec(); } - void RtpCodecParameters::FillJson(json& jsonObject) const + flatbuffers::Offset RtpCodecParameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add mimeType. - jsonObject["mimeType"] = this->mimeType.ToString(); + auto parameters = this->parameters.FillBuffer(builder); - // Add payloadType. - jsonObject["payloadType"] = this->payloadType; + std::vector> rtcpFeedback; + rtcpFeedback.reserve(this->rtcpFeedback.size()); - // Add clockRate. - jsonObject["clockRate"] = this->clockRate; - - // Add channels. - if (this->channels > 1) - jsonObject["channels"] = this->channels; - - // Add parameters. - this->parameters.FillJson(jsonObject["parameters"]); - - // Add rtcpFeedback. - jsonObject["rtcpFeedback"] = json::array(); - auto jsonRtcpFeedbackIt = jsonObject.find("rtcpFeedback"); - - for (size_t i{ 0 }; i < this->rtcpFeedback.size(); ++i) + for (const auto& fb : this->rtcpFeedback) { - jsonRtcpFeedbackIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonRtcpFeedbackIt)[i]; - auto& fb = this->rtcpFeedback[i]; - - fb.FillJson(jsonEntry); + rtcpFeedback.emplace_back(fb.FillBuffer(builder)); } + + return FBS::RtpParameters::CreateRtpCodecParametersDirect( + builder, + this->mimeType.ToString().c_str(), + this->payloadType, + this->clockRate, + this->channels > 1 ? flatbuffers::Optional(this->channels) : flatbuffers::nullopt, + ¶meters, + &rtcpFeedback); } inline void RtpCodecParameters::CheckCodec() diff --git a/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp index 6c745802bd..a9326752be 100644 --- a/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp @@ -12,80 +12,44 @@ namespace RTC { /* Instance methods. */ - RtpEncodingParameters::RtpEncodingParameters(json& data) + RtpEncodingParameters::RtpEncodingParameters(const FBS::RtpParameters::RtpEncodingParameters* data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonSsrcIt = data.find("ssrc"); - auto jsonRidIt = data.find("rid"); - auto jsonCodecPayloadTypeIt = data.find("codecPayloadType"); - auto jsonRtxIt = data.find("rtx"); - auto jsonMaxBitrateIt = data.find("maxBitrate"); - auto jsonMaxFramerateIt = data.find("maxFramerate"); - auto jsonDtxIt = data.find("dtx"); - auto jsonScalabilityModeIt = data.find("scalabilityMode"); - // ssrc is optional. - // clang-format off - if ( - jsonSsrcIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonSsrcIt) - ) - // clang-format on - { - this->ssrc = jsonSsrcIt->get(); - } + if (data->ssrc().has_value()) + this->ssrc = data->ssrc().value(); // rid is optional. - if (jsonRidIt != data.end() && jsonRidIt->is_string()) - this->rid = jsonRidIt->get(); + if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtpEncodingParameters::VT_RID)) + this->rid = data->rid()->str(); // codecPayloadType is optional. - // clang-format off - if ( - jsonCodecPayloadTypeIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonCodecPayloadTypeIt) - ) - // clang-format on + if (data->codecPayloadType().has_value()) { - this->codecPayloadType = jsonCodecPayloadTypeIt->get(); + this->codecPayloadType = data->codecPayloadType().value(); this->hasCodecPayloadType = true; } // rtx is optional. - // This may throw. - if (jsonRtxIt != data.end() && jsonRtxIt->is_object()) + if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtpEncodingParameters::VT_RTX)) { - this->rtx = RtpRtxParameters(*jsonRtxIt); + this->rtx = RtpRtxParameters(data->rtx()); this->hasRtx = true; } // maxBitrate is optional. - // clang-format off - if ( - jsonMaxBitrateIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonMaxBitrateIt) - ) - // clang-format on - { - this->maxBitrate = jsonMaxBitrateIt->get(); - } - - // maxFramerate is optional. - if (jsonMaxFramerateIt != data.end() && jsonMaxFramerateIt->is_number()) - this->maxFramerate = jsonMaxFramerateIt->get(); + if (data->maxBitrate().has_value()) + this->maxBitrate = data->maxBitrate().value(); - // dtx is optional. - if (jsonDtxIt != data.end() && jsonDtxIt->is_boolean()) - this->dtx = jsonDtxIt->get(); + // dtx is optional, default is false. + this->dtx = data->dtx(); // scalabilityMode is optional. - if (jsonScalabilityModeIt != data.end() && jsonScalabilityModeIt->is_string()) + if (flatbuffers::IsFieldPresent( + data, FBS::RtpParameters::RtpEncodingParameters::VT_SCALABILITYMODE)) { - std::string scalabilityMode = jsonScalabilityModeIt->get(); + const std::string scalabilityMode = data->scalabilityMode()->str(); static const std::regex ScalabilityModeRegex( "^[LS]([1-9]\\d{0,1})T([1-9]\\d{0,1})(_KEY)?.*", std::regex_constants::ECMAScript); @@ -112,48 +76,19 @@ namespace RTC } } - void RtpEncodingParameters::FillJson(json& jsonObject) const + flatbuffers::Offset RtpEncodingParameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Force it to be an object even if no key/values are added below. - jsonObject = json::object(); - - // Add ssrc. - if (this->ssrc != 0u) - jsonObject["ssrc"] = this->ssrc; - - // Add rid. - if (!this->rid.empty()) - jsonObject["rid"] = this->rid; - - // Add codecPayloadType. - if (this->hasCodecPayloadType) - jsonObject["codecPayloadType"] = this->codecPayloadType; - - // Add rtx. - if (this->hasRtx) - this->rtx.FillJson(jsonObject["rtx"]); - - // Add maxBitrate. - if (this->maxBitrate != 0u) - jsonObject["maxBitrate"] = this->maxBitrate; - - // Add maxFramerate. - if (this->maxFramerate > 0) - jsonObject["maxFramerate"] = this->maxFramerate; - - // Add dtx. - if (this->dtx) - jsonObject["dtx"] = this->dtx; - - // Add scalabilityMode. - if (!this->scalabilityMode.empty()) - { - jsonObject["scalabilityMode"] = this->scalabilityMode; - jsonObject["spatialLayers"] = this->spatialLayers; - jsonObject["temporalLayers"] = this->temporalLayers; - jsonObject["ksvc"] = this->ksvc; - } + return FBS::RtpParameters::CreateRtpEncodingParametersDirect( + builder, + this->ssrc != 0u ? flatbuffers::Optional(this->ssrc) : flatbuffers::nullopt, + this->rid.size() > 0 ? this->rid.c_str() : nullptr, + this->hasCodecPayloadType ? flatbuffers::Optional(this->codecPayloadType) + : flatbuffers::nullopt, + this->hasRtx ? this->rtx.FillBuffer(builder) : 0u, + this->dtx, + this->scalabilityMode.size() > 0 ? this->scalabilityMode.c_str() : nullptr); } } // namespace RTC diff --git a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp index bb762881bc..9eadc74475 100644 --- a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp @@ -10,23 +10,13 @@ namespace RTC { /* Instance methods. */ - RtpHeaderExtensionParameters::RtpHeaderExtensionParameters(json& data) + RtpHeaderExtensionParameters::RtpHeaderExtensionParameters( + const FBS::RtpParameters::RtpHeaderExtensionParameters* const data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonUriIt = data.find("uri"); - auto jsonIdIt = data.find("id"); - auto jsonEncryptIt = data.find("encrypt"); - auto jsonParametersIt = data.find("parameters"); - // uri is mandatory. - if (jsonUriIt == data.end() || !jsonUriIt->is_string()) - MS_THROW_TYPE_ERROR("missing uri"); - - this->uri = jsonUriIt->get(); + this->uri = data->uri()->str(); if (this->uri.empty()) MS_THROW_TYPE_ERROR("empty uri"); @@ -34,39 +24,31 @@ namespace RTC // Get the type. this->type = RTC::RtpHeaderExtensionUri::GetType(this->uri); - // id is mandatory. - if (jsonIdIt == data.end() || !Utils::Json::IsPositiveInteger(*jsonIdIt)) - MS_THROW_TYPE_ERROR("missing id"); - - this->id = jsonIdIt->get(); + this->id = data->id(); // Don't allow id 0. if (this->id == 0u) MS_THROW_TYPE_ERROR("invalid id 0"); - // encrypt is optional. - if (jsonEncryptIt != data.end() && jsonEncryptIt->is_boolean()) - this->encrypt = jsonEncryptIt->get(); + // encrypt is false by default. + this->encrypt = data->encrypt(); // parameters is optional. - if (jsonParametersIt != data.end() && jsonParametersIt->is_object()) - this->parameters.Set(*jsonParametersIt); + if (flatbuffers::IsFieldPresent( + data, FBS::RtpParameters::RtpHeaderExtensionParameters::VT_PARAMETERS)) + { + this->parameters.Set(data->parameters()); + } } - void RtpHeaderExtensionParameters::FillJson(json& jsonObject) const + flatbuffers::Offset RtpHeaderExtensionParameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add uri. - jsonObject["uri"] = this->uri; - - // Add id. - jsonObject["id"] = this->id; - - // Add encrypt. - jsonObject["encrypt"] = this->encrypt; + auto parameters = this->parameters.FillBuffer(builder); - // Add parameters. - this->parameters.FillJson(jsonObject["parameters"]); + return FBS::RtpParameters::CreateRtpHeaderExtensionParametersDirect( + builder, this->uri.c_str(), this->id, this->encrypt, ¶meters); } } // namespace RTC diff --git a/worker/src/RTC/RtpDictionaries/RtpParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpParameters.cpp index 2a0010affa..a11567e89d 100644 --- a/worker/src/RTC/RtpDictionaries/RtpParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpParameters.cpp @@ -38,7 +38,7 @@ namespace RTC if (rtpParameters.encodings.size() == 1) { - auto& encoding = rtpParameters.encodings[0]; + const auto& encoding = rtpParameters.encodings[0]; const auto* mediaCodec = rtpParameters.GetCodecForEncoding(const_cast(encoding)); @@ -104,35 +104,22 @@ namespace RTC /* Instance methods. */ - RtpParameters::RtpParameters(json& data) + RtpParameters::RtpParameters(const FBS::RtpParameters::RtpParameters* data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonMidIt = data.find("mid"); - auto jsonCodecsIt = data.find("codecs"); - auto jsonEncodingsIt = data.find("encodings"); - auto jsonHeaderExtensionsIt = data.find("headerExtensions"); - auto jsonRtcpIt = data.find("rtcp"); - // mid is optional. - if (jsonMidIt != data.end() && jsonMidIt->is_string()) + if (data->mid()) { - this->mid = jsonMidIt->get(); + this->mid = data->mid()->str(); if (this->mid.empty()) MS_THROW_TYPE_ERROR("empty mid"); } - // codecs is mandatory. - if (jsonCodecsIt == data.end() || !jsonCodecsIt->is_array()) - MS_THROW_TYPE_ERROR("missing codecs"); + this->codecs.reserve(data->codecs()->size()); - this->codecs.reserve(jsonCodecsIt->size()); - - for (auto& entry : *jsonCodecsIt) + for (const auto* entry : *data->codecs()) { // This may throw due the constructor of RTC::RtpCodecParameters. this->codecs.emplace_back(entry); @@ -142,12 +129,12 @@ namespace RTC MS_THROW_TYPE_ERROR("empty codecs"); // encodings is mandatory. - if (jsonEncodingsIt == data.end() || !jsonEncodingsIt->is_array()) + if (!flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtpParameters::VT_ENCODINGS)) MS_THROW_TYPE_ERROR("missing encodings"); - this->encodings.reserve(jsonEncodingsIt->size()); + this->encodings.reserve(data->encodings()->size()); - for (auto& entry : *jsonEncodingsIt) + for (const auto* entry : *data->encodings()) { // This may throw due the constructor of RTC::RtpEncodingParameters. this->encodings.emplace_back(entry); @@ -157,11 +144,11 @@ namespace RTC MS_THROW_TYPE_ERROR("empty encodings"); // headerExtensions is optional. - if (jsonHeaderExtensionsIt != data.end() && jsonHeaderExtensionsIt->is_array()) + if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtpParameters::VT_HEADEREXTENSIONS)) { - this->headerExtensions.reserve(jsonHeaderExtensionsIt->size()); + this->headerExtensions.reserve(data->headerExtensions()->size()); - for (auto& entry : *jsonHeaderExtensionsIt) + for (const auto* entry : *data->headerExtensions()) { // This may throw due the constructor of RTC::RtpHeaderExtensionParameters. this->headerExtensions.emplace_back(entry); @@ -169,10 +156,10 @@ namespace RTC } // rtcp is optional. - if (jsonRtcpIt != data.end() && jsonRtcpIt->is_object()) + if (flatbuffers::IsFieldPresent(data, FBS::RtpParameters::RtpParameters::VT_RTCP)) { // This may throw. - this->rtcp = RTC::RtcpParameters(*jsonRtcpIt); + this->rtcp = RTC::RtcpParameters(data->rtcp()); this->hasRtcp = true; } @@ -181,61 +168,46 @@ namespace RTC ValidateEncodings(); } - void RtpParameters::FillJson(json& jsonObject) const + flatbuffers::Offset RtpParameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add mid. - if (!this->mid.empty()) - jsonObject["mid"] = this->mid; - // Add codecs. - jsonObject["codecs"] = json::array(); - auto jsonCodecsIt = jsonObject.find("codecs"); + std::vector> codecs; + codecs.reserve(this->codecs.size()); - for (size_t i{ 0 }; i < this->codecs.size(); ++i) + for (const auto& codec : this->codecs) { - jsonCodecsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonCodecsIt)[i]; - auto& codec = this->codecs[i]; - - codec.FillJson(jsonEntry); + codecs.emplace_back(codec.FillBuffer(builder)); } // Add encodings. - jsonObject["encodings"] = json::array(); - auto jsonEncodingsIt = jsonObject.find("encodings"); + std::vector> encodings; + encodings.reserve(this->encodings.size()); - for (size_t i{ 0 }; i < this->encodings.size(); ++i) + for (const auto& encoding : this->encodings) { - jsonEncodingsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonEncodingsIt)[i]; - auto& encoding = this->encodings[i]; - - encoding.FillJson(jsonEntry); + encodings.emplace_back(encoding.FillBuffer(builder)); } // Add headerExtensions. - jsonObject["headerExtensions"] = json::array(); - auto jsonHeaderExtensionsIt = jsonObject.find("headerExtensions"); + std::vector> headerExtensions; + headerExtensions.reserve(this->headerExtensions.size()); - for (size_t i{ 0 }; i < this->headerExtensions.size(); ++i) + for (const auto& headerExtension : this->headerExtensions) { - jsonHeaderExtensionsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonHeaderExtensionsIt)[i]; - auto& headerExtension = this->headerExtensions[i]; - - headerExtension.FillJson(jsonEntry); + headerExtensions.emplace_back(headerExtension.FillBuffer(builder)); } // Add rtcp. + flatbuffers::Offset rtcp; + if (this->hasRtcp) - this->rtcp.FillJson(jsonObject["rtcp"]); - else - jsonObject["rtcp"] = json::object(); + rtcp = this->rtcp.FillBuffer(builder); + + return FBS::RtpParameters::CreateRtpParametersDirect( + builder, mid.c_str(), &codecs, &headerExtensions, &encodings, rtcp); } const RTC::RtpCodecParameters* RtpParameters::GetCodecForEncoding(RtpEncodingParameters& encoding) const @@ -247,7 +219,7 @@ namespace RTC for (; it != this->codecs.end(); ++it) { - auto& codec = *it; + const auto& codec = *it; if (codec.payloadType == payloadType) return std::addressof(codec); diff --git a/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp index eaf8726395..41272388b1 100644 --- a/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp @@ -10,36 +10,18 @@ namespace RTC { /* Instance methods. */ - RtpRtxParameters::RtpRtxParameters(json& data) + RtpRtxParameters::RtpRtxParameters(const FBS::RtpParameters::Rtx* data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonSsrcIt = data.find("ssrc"); - - // ssrc is optional. - // clang-format off - if ( - jsonSsrcIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonSsrcIt) - ) - // clang-format on - { - this->ssrc = jsonSsrcIt->get(); - } + this->ssrc = data->ssrc(); } - void RtpRtxParameters::FillJson(json& jsonObject) const + flatbuffers::Offset RtpRtxParameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Force it to be an object even if no key/values are added below. - jsonObject = json::object(); - - // Add ssrc (optional). - if (this->ssrc != 0u) - jsonObject["ssrc"] = this->ssrc; + return FBS::RtpParameters::CreateRtx(builder, this->ssrc); } } // namespace RTC diff --git a/worker/src/RTC/RtpListener.cpp b/worker/src/RTC/RtpListener.cpp index 5c21c60cf9..e8a4e43e24 100644 --- a/worker/src/RTC/RtpListener.cpp +++ b/worker/src/RTC/RtpListener.cpp @@ -10,44 +10,48 @@ namespace RTC { /* Instance methods. */ - void RtpListener::FillJson(json& jsonObject) const + flatbuffers::Offset RtpListener::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - jsonObject["ssrcTable"] = json::object(); - jsonObject["midTable"] = json::object(); - jsonObject["ridTable"] = json::object(); - - auto jsonSsrcTableIt = jsonObject.find("ssrcTable"); - auto jsonMidTableIt = jsonObject.find("midTable"); - auto jsonRidTableIt = jsonObject.find("ridTable"); - // Add ssrcTable. + std::vector> ssrcTable; + for (const auto& kv : this->ssrcTable) { auto ssrc = kv.first; auto* producer = kv.second; - (*jsonSsrcTableIt)[std::to_string(ssrc)] = producer->id; + ssrcTable.emplace_back( + FBS::Common::CreateUint32StringDirect(builder, ssrc, producer->id.c_str())); } // Add midTable. + std::vector> midTable; + for (const auto& kv : this->midTable) { const auto& mid = kv.first; auto* producer = kv.second; - (*jsonMidTableIt)[mid] = producer->id; + midTable.emplace_back( + FBS::Common::CreateStringStringDirect(builder, mid.c_str(), producer->id.c_str())); } // Add ridTable. + std::vector> ridTable; + for (const auto& kv : this->ridTable) { const auto& rid = kv.first; auto* producer = kv.second; - (*jsonRidTableIt)[rid] = producer->id; + ridTable.emplace_back( + FBS::Common::CreateStringStringDirect(builder, rid.c_str(), producer->id.c_str())); } + + return FBS::Transport::CreateRtpListenerDirect(builder, &ssrcTable, &midTable, &ridTable); } void RtpListener::AddProducer(RTC::Producer* producer) diff --git a/worker/src/RTC/RtpObserver.cpp b/worker/src/RTC/RtpObserver.cpp index e57dfe542b..b7db32ce1a 100644 --- a/worker/src/RTC/RtpObserver.cpp +++ b/worker/src/RTC/RtpObserver.cpp @@ -24,9 +24,9 @@ namespace RTC { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::RTP_OBSERVER_PAUSE: + case Channel::ChannelRequest::Method::RTP_OBSERVER_PAUSE: { this->Pause(); @@ -35,7 +35,7 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::RTP_OBSERVER_RESUME: + case Channel::ChannelRequest::Method::RTP_OBSERVER_RESUME: { this->Resume(); @@ -44,10 +44,11 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::RTP_OBSERVER_ADD_PRODUCER: + case Channel::ChannelRequest::Method::RTP_OBSERVER_ADD_PRODUCER: { - // This may throw. - auto producerId = GetProducerIdFromData(request->data); + const auto* body = request->data->body_as(); + auto producerId = body->producerId()->str(); + RTC::Producer* producer = this->listener->RtpObserverGetProducer(this, producerId); this->AddProducer(producer); @@ -59,10 +60,11 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::RTP_OBSERVER_REMOVE_PRODUCER: + case Channel::ChannelRequest::Method::RTP_OBSERVER_REMOVE_PRODUCER: { - // This may throw. - auto producerId = GetProducerIdFromData(request->data); + const auto* body = request->data->body_as(); + auto producerId = body->producerId()->str(); + RTC::Producer* producer = this->listener->RtpObserverGetProducer(this, producerId); this->RemoveProducer(producer); @@ -77,7 +79,7 @@ namespace RTC default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } } @@ -105,16 +107,4 @@ namespace RTC Resumed(); } - - std::string RtpObserver::GetProducerIdFromData(json& data) const - { - MS_TRACE(); - - auto jsonRouterIdIt = data.find("producerId"); - - if (jsonRouterIdIt == data.end() || !jsonRouterIdIt->is_string()) - MS_THROW_ERROR("missing data.producerId"); - - return jsonRouterIdIt->get(); - } } // namespace RTC diff --git a/worker/src/RTC/RtpPacket.cpp b/worker/src/RTC/RtpPacket.cpp index 368115abed..64a2b5a55d 100644 --- a/worker/src/RTC/RtpPacket.cpp +++ b/worker/src/RTC/RtpPacket.cpp @@ -317,65 +317,6 @@ namespace RTC MS_DUMP(""); } - void RtpPacket::FillJson(json& jsonObject) const - { - MS_TRACE(); - - // Add payloadType. - jsonObject["payloadType"] = GetPayloadType(); - - // Add sequenceNumber. - jsonObject["sequenceNumber"] = GetSequenceNumber(); - - // Add timestamp. - jsonObject["timestamp"] = GetTimestamp(); - - // Add marker. - jsonObject["marker"] = HasMarker(); - - // Add ssrc. - jsonObject["ssrc"] = GetSsrc(); - - // Add isKeyFrame. - jsonObject["isKeyFrame"] = IsKeyFrame(); - - // Add size. - jsonObject["size"] = GetSize(); - - // Add payloadSize. - jsonObject["payloadSize"] = GetPayloadLength(); - - // Add spatialLayer. - jsonObject["spatialLayer"] = GetSpatialLayer(); - - // Add temporalLayer. - jsonObject["temporalLayer"] = GetTemporalLayer(); - - // Add mid. - std::string mid; - - if (this->midExtensionId != 0u && ReadMid(mid)) - jsonObject["mid"] = mid; - - // Add rid. - std::string rid; - - if (this->ridExtensionId != 0u && ReadRid(rid)) - jsonObject["rid"] = rid; - - // Add rrid. - std::string rrid; - - if (this->rridExtensionId != 0u && ReadRid(rrid)) - jsonObject["rrid"] = rrid; - - // Add wideSequenceNumber. - uint16_t wideSequenceNumber; - - if (this->transportWideCc01ExtensionId != 0u && ReadTransportWideCc01(wideSequenceNumber)) - jsonObject["wideSequenceNumber"] = wideSequenceNumber; - } - void RtpPacket::SetExtensions(uint8_t type, const std::vector& extensions) { MS_ASSERT(type == 1u || type == 2u, "type must be 1 or 2"); diff --git a/worker/src/RTC/RtpStream.cpp b/worker/src/RTC/RtpStream.cpp index 85b6850b81..35bf431d79 100644 --- a/worker/src/RTC/RtpStream.cpp +++ b/worker/src/RTC/RtpStream.cpp @@ -31,53 +31,54 @@ namespace RTC this->rtxStream = nullptr; } - void RtpStream::FillJson(json& jsonObject) const + flatbuffers::Offset RtpStream::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); // Add params. - this->params.FillJson(jsonObject["params"]); - - // Add score. - jsonObject["score"] = this->score; + auto params = this->params.FillBuffer(builder); // Add rtxStream. + flatbuffers::Offset rtxStream; + if (HasRtx()) - this->rtxStream->FillJson(jsonObject["rtxStream"]); + rtxStream = this->rtxStream->FillBuffer(builder); + + return FBS::RtpStream::CreateDump(builder, params, this->score, rtxStream); } - void RtpStream::FillJsonStats(json& jsonObject) + flatbuffers::Offset RtpStream::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); const uint64_t nowMs = DepLibUV::GetTimeMs(); - jsonObject["timestamp"] = nowMs; - jsonObject["ssrc"] = this->params.ssrc; - jsonObject["kind"] = RtpCodecMimeType::type2String[this->params.mimeType.type]; - jsonObject["mimeType"] = this->params.mimeType.ToString(); - jsonObject["packetsLost"] = this->packetsLost; - jsonObject["fractionLost"] = this->fractionLost; - jsonObject["packetsDiscarded"] = this->packetsDiscarded; - jsonObject["packetsRetransmitted"] = this->packetsRetransmitted; - jsonObject["packetsRepaired"] = this->packetsRepaired; - jsonObject["nackCount"] = this->nackCount; - jsonObject["nackPacketCount"] = this->nackPacketCount; - jsonObject["pliCount"] = this->pliCount; - jsonObject["firCount"] = this->firCount; - jsonObject["score"] = this->score; - - if (!this->params.rid.empty()) - jsonObject["rid"] = this->params.rid; - - if (this->params.rtxSsrc) - jsonObject["rtxSsrc"] = this->params.rtxSsrc; - - if (this->rtxStream) - jsonObject["rtxPacketsDiscarded"] = this->rtxStream->GetPacketsDiscarded(); - - if (this->hasRtt) - jsonObject["roundTripTime"] = this->rtt; + auto baseStats = FBS::RtpStream::CreateBaseStatsDirect( + builder, + nowMs, + this->params.ssrc, + FBS::RtpParameters::MediaKind(this->params.mimeType.type), + this->params.mimeType.ToString().c_str(), + this->packetsLost, + this->fractionLost, + this->packetsDiscarded, + this->packetsRetransmitted, + this->packetsRepaired, + this->nackCount, + this->nackPacketCount, + this->pliCount, + this->firCount, + this->score, + !this->params.rid.empty() ? this->params.rid.c_str() : nullptr, + this->params.rtxSsrc ? flatbuffers::Optional(this->params.rtxSsrc) + : flatbuffers::nullopt, + this->rtxStream ? this->rtxStream->GetPacketsDiscarded() : 0, + this->hasRtt ? this->rtt : 0); + + return FBS::RtpStream::CreateStats( + builder, FBS::RtpStream::StatsData::BaseStats, baseStats.Union()); } void RtpStream::SetRtx(uint8_t payloadType, uint32_t ssrc) @@ -338,33 +339,28 @@ namespace RTC this->badSeq = RtpSeqMod + 1; // So seq == badSeq is false. } - void RtpStream::Params::FillJson(json& jsonObject) const + flatbuffers::Offset RtpStream::Params::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - jsonObject["encodingIdx"] = this->encodingIdx; - jsonObject["ssrc"] = this->ssrc; - jsonObject["payloadType"] = this->payloadType; - jsonObject["mimeType"] = this->mimeType.ToString(); - jsonObject["clockRate"] = this->clockRate; - - if (!this->rid.empty()) - jsonObject["rid"] = this->rid; - - jsonObject["cname"] = this->cname; - - if (this->rtxSsrc != 0) - { - jsonObject["rtxSsrc"] = this->rtxSsrc; - jsonObject["rtxPayloadType"] = this->rtxPayloadType; - } - - jsonObject["useNack"] = this->useNack; - jsonObject["usePli"] = this->usePli; - jsonObject["useFir"] = this->useFir; - jsonObject["useInBandFec"] = this->useInBandFec; - jsonObject["useDtx"] = this->useDtx; - jsonObject["spatialLayers"] = this->spatialLayers; - jsonObject["temporalLayers"] = this->temporalLayers; + return FBS::RtpStream::CreateParamsDirect( + builder, + this->encodingIdx, + this->ssrc, + this->payloadType, + this->mimeType.ToString().c_str(), + this->clockRate, + this->rid.c_str(), + this->cname.c_str(), + this->rtxSsrc != 0 ? flatbuffers::Optional(this->rtxSsrc) : flatbuffers::nullopt, + this->rtxSsrc != 0 ? flatbuffers::Optional(this->rtxPayloadType) : flatbuffers::nullopt, + this->useNack, + this->usePli, + this->useFir, + this->useInBandFec, + this->useDtx, + this->spatialLayers, + this->temporalLayers); } } // namespace RTC diff --git a/worker/src/RTC/RtpStreamRecv.cpp b/worker/src/RTC/RtpStreamRecv.cpp index abee7f293b..a9a09ebd5e 100644 --- a/worker/src/RTC/RtpStreamRecv.cpp +++ b/worker/src/RTC/RtpStreamRecv.cpp @@ -158,9 +158,9 @@ namespace RTC size_t packetCount{ 0u }; - for (auto& spatialLayerCounter : this->spatialLayerCounters) + for (const auto& spatialLayerCounter : this->spatialLayerCounters) { - for (auto& temporalLayerCounter : spatialLayerCounter) + for (const auto& temporalLayerCounter : spatialLayerCounter) { packetCount += temporalLayerCounter.GetPacketCount(); } @@ -227,34 +227,41 @@ namespace RTC this->inactivityCheckPeriodicTimer = nullptr; } - void RtpStreamRecv::FillJsonStats(json& jsonObject) + flatbuffers::Offset RtpStreamRecv::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); const uint64_t nowMs = DepLibUV::GetTimeMs(); - RTC::RtpStream::FillJsonStats(jsonObject); + auto baseStats = RTC::RtpStream::FillBufferStats(builder); - jsonObject["type"] = "inbound-rtp"; - jsonObject["jitter"] = this->jitter; - jsonObject["packetCount"] = this->transmissionCounter.GetPacketCount(); - jsonObject["byteCount"] = this->transmissionCounter.GetBytes(); - jsonObject["bitrate"] = this->transmissionCounter.GetBitrate(nowMs); + std::vector> bitrateByLayer; if (GetSpatialLayers() > 1 || GetTemporalLayers() > 1) { - jsonObject["bitrateByLayer"] = json::object(); - auto jsonBitrateByLayerIt = jsonObject.find("bitrateByLayer"); - for (uint8_t sIdx = 0; sIdx < GetSpatialLayers(); ++sIdx) { for (uint8_t tIdx = 0; tIdx < GetTemporalLayers(); ++tIdx) { - (*jsonBitrateByLayerIt)[std::to_string(sIdx) + "." + std::to_string(tIdx)] = - GetBitrate(nowMs, sIdx, tIdx); + auto layer = std::to_string(sIdx) + "." + std::to_string(tIdx); + + bitrateByLayer.emplace_back(FBS::RtpStream::CreateBitrateByLayerDirect( + builder, layer.c_str(), GetBitrate(nowMs, sIdx, tIdx))); } } } + + auto stats = FBS::RtpStream::CreateRecvStatsDirect( + builder, + baseStats, + this->jitter, + this->transmissionCounter.GetPacketCount(), + this->transmissionCounter.GetBytes(), + this->transmissionCounter.GetBitrate(nowMs), + &bitrateByLayer); + + return FBS::RtpStream::CreateStats(builder, FBS::RtpStream::StatsData::RecvStats, stats.Union()); } bool RtpStreamRecv::ReceivePacket(RTC::RtpPacket* packet) diff --git a/worker/src/RTC/RtpStreamSend.cpp b/worker/src/RTC/RtpStreamSend.cpp index b8949a37ff..74d3a67a70 100644 --- a/worker/src/RTC/RtpStreamSend.cpp +++ b/worker/src/RTC/RtpStreamSend.cpp @@ -72,18 +72,22 @@ namespace RTC this->retransmissionBuffer = nullptr; } - void RtpStreamSend::FillJsonStats(json& jsonObject) + flatbuffers::Offset RtpStreamSend::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); const uint64_t nowMs = DepLibUV::GetTimeMs(); - RTC::RtpStream::FillJsonStats(jsonObject); + auto baseStats = RTC::RtpStream::FillBufferStats(builder); + auto stats = FBS::RtpStream::CreateSendStats( + builder, + baseStats, + this->transmissionCounter.GetPacketCount(), + this->transmissionCounter.GetBytes(), + this->transmissionCounter.GetBitrate(nowMs)); - jsonObject["type"] = "outbound-rtp"; - jsonObject["packetCount"] = this->transmissionCounter.GetPacketCount(); - jsonObject["byteCount"] = this->transmissionCounter.GetBytes(); - jsonObject["bitrate"] = this->transmissionCounter.GetBitrate(nowMs); + return FBS::RtpStream::CreateStats(builder, FBS::RtpStream::StatsData::SendStats, stats.Union()); } void RtpStreamSend::SetRtx(uint8_t payloadType, uint32_t ssrc) diff --git a/worker/src/RTC/RtxStream.cpp b/worker/src/RTC/RtxStream.cpp index 44b5c3bc12..6f900906f4 100644 --- a/worker/src/RTC/RtxStream.cpp +++ b/worker/src/RTC/RtxStream.cpp @@ -28,12 +28,15 @@ namespace RTC MS_TRACE(); } - void RtxStream::FillJson(json& jsonObject) const + flatbuffers::Offset RtxStream::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); // Add params. - this->params.FillJson(jsonObject["params"]); + auto params = this->params.FillBuffer(builder); + + return FBS::RtxStream::CreateRtxDump(builder, params); } bool RtxStream::ReceivePacket(RTC::RtpPacket* packet) @@ -231,18 +234,18 @@ namespace RTC this->badSeq = RtpSeqMod + 1; // So seq == badSeq is false. } - void RtxStream::Params::FillJson(json& jsonObject) const + flatbuffers::Offset RtxStream::Params::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - jsonObject["ssrc"] = this->ssrc; - jsonObject["payloadType"] = this->payloadType; - jsonObject["mimeType"] = this->mimeType.ToString(); - jsonObject["clockRate"] = this->clockRate; - - if (!this->rrid.empty()) - jsonObject["rrid"] = this->rrid; - - jsonObject["cname"] = this->cname; + return FBS::RtxStream::CreateParamsDirect( + builder, + this->ssrc, + this->payloadType, + this->mimeType.ToString().c_str(), + this->clockRate, + this->rrid.c_str(), + this->cname.c_str()); } } // namespace RTC diff --git a/worker/src/RTC/SctpAssociation.cpp b/worker/src/RTC/SctpAssociation.cpp index 8a5b6c2df6..89f9bf525f 100644 --- a/worker/src/RTC/SctpAssociation.cpp +++ b/worker/src/RTC/SctpAssociation.cpp @@ -341,30 +341,27 @@ namespace RTC } } - void SctpAssociation::FillJson(json& jsonObject) const + flatbuffers::Offset SctpAssociation::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add port (always 5000). - jsonObject["port"] = 5000; - - // Add OS. - jsonObject["OS"] = this->os; - - // Add MIS. - jsonObject["MIS"] = this->mis; - - // Add maxMessageSize. - jsonObject["maxMessageSize"] = this->maxSctpMessageSize; - - // Add sendBufferSize. - jsonObject["sendBufferSize"] = this->sctpSendBufferSize; - - // Add sctpBufferedAmountLowThreshold. - jsonObject["sctpBufferedAmount"] = this->sctpBufferedAmount; - - // Add isDataChannel. - jsonObject["isDataChannel"] = this->isDataChannel; + return FBS::SctpParameters::CreateSctpParameters( + builder, + // Add port (always 5000). + 5000, + // Add OS. + this->os, + // Add MIS. + this->mis, + // Add maxMessageSize. + this->maxSctpMessageSize, + // Add sendBufferSize. + this->sctpSendBufferSize, + // Add sctpBufferedAmountLowThreshold. + this->sctpBufferedAmount, + // Add isDataChannel. + this->isDataChannel); } void SctpAssociation::ProcessSctpData(const uint8_t* data, size_t len) diff --git a/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp b/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp index 5a6e4156c5..1634783876 100644 --- a/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp +++ b/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp @@ -10,23 +10,11 @@ namespace RTC { /* Instance methods. */ - SctpStreamParameters::SctpStreamParameters(json& data) + SctpStreamParameters::SctpStreamParameters(const FBS::SctpParameters::SctpStreamParameters* data) { MS_TRACE(); - if (!data.is_object()) - MS_THROW_TYPE_ERROR("data is not an object"); - - auto jsonStreamIdIt = data.find("streamId"); - auto jsonOrderedIdIt = data.find("ordered"); - auto jsonMaxPacketLifeTimeIt = data.find("maxPacketLifeTime"); - auto jsonMaxRetransmitsIt = data.find("maxRetransmits"); - - // streamId is mandatory. - if (jsonStreamIdIt == data.end() || !Utils::Json::IsPositiveInteger(*jsonStreamIdIt)) - MS_THROW_TYPE_ERROR("missing streamId"); - - this->streamId = jsonStreamIdIt->get(); + this->streamId = data->streamId(); if (this->streamId > 65534) MS_THROW_TYPE_ERROR("streamId must not be greater than 65534"); @@ -34,32 +22,22 @@ namespace RTC // ordered is optional. bool orderedGiven = false; - if (jsonOrderedIdIt != data.end() && jsonOrderedIdIt->is_boolean()) + if (data->ordered().has_value()) { orderedGiven = true; - this->ordered = jsonOrderedIdIt->get(); + this->ordered = data->ordered().value(); } // maxPacketLifeTime is optional. - // clang-format off - if ( - jsonMaxPacketLifeTimeIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonMaxPacketLifeTimeIt) - ) - // clang-format on + if (data->maxPacketLifeTime().has_value()) { - this->maxPacketLifeTime = jsonMaxPacketLifeTimeIt->get(); + this->maxPacketLifeTime = data->maxPacketLifeTime().value(); } // maxRetransmits is optional. - // clang-format off - if ( - jsonMaxRetransmitsIt != data.end() && - Utils::Json::IsPositiveInteger(*jsonMaxRetransmitsIt) - ) - // clang-format on + if (data->maxRetransmits().has_value()) { - this->maxRetransmits = jsonMaxRetransmitsIt->get(); + this->maxRetransmits = data->maxRetransmits().value(); } if (this->maxPacketLifeTime && this->maxRetransmits) @@ -81,22 +59,18 @@ namespace RTC } } - void SctpStreamParameters::FillJson(json& jsonObject) const + flatbuffers::Offset SctpStreamParameters::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add streamId. - jsonObject["streamId"] = this->streamId; - - // Add ordered. - jsonObject["ordered"] = this->ordered; - - // Add maxPacketLifeTime. - if (this->maxPacketLifeTime) - jsonObject["maxPacketLifeTime"] = this->maxPacketLifeTime; - - // Add maxRetransmits. - if (this->maxRetransmits) - jsonObject["maxRetransmits"] = this->maxRetransmits; + return FBS::SctpParameters::CreateSctpStreamParameters( + builder, + this->streamId, + this->ordered, + this->maxPacketLifeTime ? flatbuffers::Optional(this->maxPacketLifeTime) + : flatbuffers::nullopt, + this->maxRetransmits ? flatbuffers::Optional(this->maxRetransmits) + : flatbuffers::nullopt); } } // namespace RTC diff --git a/worker/src/RTC/SctpListener.cpp b/worker/src/RTC/SctpListener.cpp index 64300c6c0a..3daf7aa76f 100644 --- a/worker/src/RTC/SctpListener.cpp +++ b/worker/src/RTC/SctpListener.cpp @@ -10,22 +10,24 @@ namespace RTC { /* Instance methods. */ - void SctpListener::FillJson(json& jsonObject) const + flatbuffers::Offset SctpListener::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - jsonObject["streamIdTable"] = json::object(); - - auto jsonStreamIdTableIt = jsonObject.find("streamIdTable"); - // Add streamIdTable. + std::vector> streamIdTable; + for (const auto& kv : this->streamIdTable) { auto streamId = kv.first; auto* dataProducer = kv.second; - (*jsonStreamIdTableIt)[std::to_string(streamId)] = dataProducer->id; + streamIdTable.emplace_back( + FBS::Common::CreateUint16StringDirect(builder, streamId, dataProducer->id.c_str())); } + + return FBS::Transport::CreateSctpListenerDirect(builder, &streamIdTable); } void SctpListener::AddDataProducer(RTC::DataProducer* dataProducer) diff --git a/worker/src/RTC/Shared.cpp b/worker/src/RTC/Shared.cpp index e984862df0..037eca59c8 100644 --- a/worker/src/RTC/Shared.cpp +++ b/worker/src/RTC/Shared.cpp @@ -7,11 +7,8 @@ namespace RTC { Shared::Shared( - ChannelMessageRegistrator* channelMessageRegistrator, - Channel::ChannelNotifier* channelNotifier, - PayloadChannel::PayloadChannelNotifier* payloadChannelNotifier) - : channelMessageRegistrator(channelMessageRegistrator), channelNotifier(channelNotifier), - payloadChannelNotifier(payloadChannelNotifier) + ChannelMessageRegistrator* channelMessageRegistrator, Channel::ChannelNotifier* channelNotifier) + : channelMessageRegistrator(channelMessageRegistrator), channelNotifier(channelNotifier) { MS_TRACE(); } @@ -22,6 +19,5 @@ namespace RTC delete this->channelMessageRegistrator; delete this->channelNotifier; - delete this->payloadChannelNotifier; } } // namespace RTC diff --git a/worker/src/RTC/SimpleConsumer.cpp b/worker/src/RTC/SimpleConsumer.cpp index 01da96fb0e..5407142c66 100644 --- a/worker/src/RTC/SimpleConsumer.cpp +++ b/worker/src/RTC/SimpleConsumer.cpp @@ -16,7 +16,7 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data) + const FBS::Transport::ConsumeRequest* data) : RTC::Consumer::Consumer(shared, id, producerId, listener, data, RTC::RtpParameters::Type::SIMPLE) { MS_TRACE(); @@ -44,22 +44,15 @@ namespace RTC this->encodingContext.reset( RTC::Codecs::Tools::GetEncodingContext(mediaCodec->mimeType, params)); - auto jsonIgnoreDtx = data.find("ignoreDtx"); - - if (jsonIgnoreDtx != data.end() && jsonIgnoreDtx->is_boolean()) - { - auto ignoreDtx = jsonIgnoreDtx->get(); - - this->encodingContext->SetIgnoreDtx(ignoreDtx); - } + // ignoreDtx is set to false by default. + this->encodingContext->SetIgnoreDtx(data->ignoreDtx()); } // NOTE: This may throw. this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelNotificationHandler*/ nullptr); } SimpleConsumer::~SimpleConsumer() @@ -71,56 +64,76 @@ namespace RTC delete this->rtpStream; } - void SimpleConsumer::FillJson(json& jsonObject) const + flatbuffers::Offset SimpleConsumer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); // Call the parent method. - RTC::Consumer::FillJson(jsonObject); - + auto base = RTC::Consumer::FillBuffer(builder); // Add rtpStream. - this->rtpStream->FillJson(jsonObject["rtpStream"]); + auto rtpStream = this->rtpStream->FillBuffer(builder); + + auto simpleConsumerDump = FBS::Consumer::CreateSimpleConsumerDump(builder, base, rtpStream); + + return FBS::Consumer::CreateDumpResponse( + builder, + FBS::Consumer::DumpData::SimpleConsumerDump, + simpleConsumerDump.Union(), + FBS::RtpParameters::Type(this->type)); } - void SimpleConsumer::FillJsonStats(json& jsonArray) const + flatbuffers::Offset SimpleConsumer::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); + std::vector> rtpStreams; + // Add stats of our send stream. - jsonArray.emplace_back(json::value_t::object); - this->rtpStream->FillJsonStats(jsonArray[0]); + rtpStreams.emplace_back(this->rtpStream->FillBufferStats(builder)); // Add stats of our recv stream. if (this->producerRtpStream) { - jsonArray.emplace_back(json::value_t::object); - this->producerRtpStream->FillJsonStats(jsonArray[1]); + rtpStreams.emplace_back(this->producerRtpStream->FillBufferStats(builder)); } + + return FBS::Consumer::CreateGetStatsResponseDirect(builder, &rtpStreams); } - void SimpleConsumer::FillJsonScore(json& jsonObject) const + flatbuffers::Offset SimpleConsumer::FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); MS_ASSERT(this->producerRtpStreamScores, "producerRtpStreamScores not set"); - jsonObject["score"] = this->rtpStream->GetScore(); + uint8_t producerScore{ 0 }; if (this->producerRtpStream) - jsonObject["producerScore"] = this->producerRtpStream->GetScore(); - else - jsonObject["producerScore"] = 0; + producerScore = this->producerRtpStream->GetScore(); - jsonObject["producerScores"] = *this->producerRtpStreamScores; + return FBS::Consumer::CreateConsumerScoreDirect( + builder, this->rtpStream->GetScore(), producerScore, this->producerRtpStreamScores); } void SimpleConsumer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::CONSUMER_REQUEST_KEY_FRAME: + case Channel::ChannelRequest::Method::CONSUMER_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::FBS_Consumer_DumpResponse, dumpOffset); + + break; + } + + case Channel::ChannelRequest::Method::CONSUMER_REQUEST_KEY_FRAME: { if (IsActive()) RequestKeyFrame(); @@ -130,7 +143,7 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::CONSUMER_SET_PREFERRED_LAYERS: + case Channel::ChannelRequest::Method::CONSUMER_SET_PREFERRED_LAYERS: { // Do nothing. @@ -636,11 +649,16 @@ namespace RTC { MS_TRACE(); - json data = json::object(); + auto scoreOffset = FillBufferScore(this->shared->channelNotifier->GetBufferBuilder()); - FillJsonScore(data); + auto notificationOffset = FBS::Consumer::CreateScoreNotification( + this->shared->channelNotifier->GetBufferBuilder(), scoreOffset); - this->shared->channelNotifier->Emit(this->id, "score", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::CONSUMER_SCORE, + FBS::Notification::Body::FBS_Consumer_ScoreNotification, + notificationOffset); } inline void SimpleConsumer::OnRtpStreamScore( diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index 44076dca1f..3527f3c0ff 100644 --- a/worker/src/RTC/SimulcastConsumer.cpp +++ b/worker/src/RTC/SimulcastConsumer.cpp @@ -24,7 +24,7 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data) + const FBS::Transport::ConsumeRequest* data) : RTC::Consumer::Consumer( shared, id, producerId, listener, data, RTC::RtpParameters::Type::SIMULCAST) { @@ -43,8 +43,6 @@ namespace RTC MS_THROW_TYPE_ERROR("encoding.spatialLayers does not match number of consumableRtpEncodings"); } - auto jsonPreferredLayersIt = data.find("preferredLayers"); - // Fill mapMappedSsrcSpatialLayer. for (size_t idx{ 0u }; idx < this->consumableRtpEncodings.size(); ++idx) { @@ -54,34 +52,18 @@ namespace RTC } // Set preferredLayers (if given). - if (jsonPreferredLayersIt != data.end() && jsonPreferredLayersIt->is_object()) + if (flatbuffers::IsFieldPresent(data, FBS::Transport::ConsumeRequest::VT_PREFERREDLAYERS)) { - auto jsonSpatialLayerIt = jsonPreferredLayersIt->find("spatialLayer"); - auto jsonTemporalLayerIt = jsonPreferredLayersIt->find("temporalLayer"); - - // clang-format off - if ( - jsonSpatialLayerIt == jsonPreferredLayersIt->end() || - !Utils::Json::IsPositiveInteger(*jsonSpatialLayerIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing preferredLayers.spatialLayer"); - } + const auto* preferredLayers = data->preferredLayers(); - this->preferredSpatialLayer = jsonSpatialLayerIt->get(); + this->preferredSpatialLayer = preferredLayers->spatialLayer(); if (this->preferredSpatialLayer > encoding.spatialLayers - 1) this->preferredSpatialLayer = encoding.spatialLayers - 1; - // clang-format off - if ( - jsonTemporalLayerIt != jsonPreferredLayersIt->end() && - Utils::Json::IsPositiveInteger(*jsonTemporalLayerIt) - ) - // clang-format on + if (preferredLayers->temporalLayer().has_value()) { - this->preferredTemporalLayer = jsonTemporalLayerIt->get(); + this->preferredTemporalLayer = preferredLayers->temporalLayer().value(); if (this->preferredTemporalLayer > encoding.temporalLayers - 1) this->preferredTemporalLayer = encoding.temporalLayers - 1; @@ -129,8 +111,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelRequestHandler*/ nullptr); } SimulcastConsumer::~SimulcastConsumer() @@ -142,54 +123,57 @@ namespace RTC delete this->rtpStream; } - void SimulcastConsumer::FillJson(json& jsonObject) const + flatbuffers::Offset SimulcastConsumer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); // Call the parent method. - RTC::Consumer::FillJson(jsonObject); - + auto base = RTC::Consumer::FillBuffer(builder); // Add rtpStream. - this->rtpStream->FillJson(jsonObject["rtpStream"]); - - // Add preferredSpatialLayer. - jsonObject["preferredSpatialLayer"] = this->preferredSpatialLayer; - - // Add targetSpatialLayer. - jsonObject["targetSpatialLayer"] = this->targetSpatialLayer; + auto rtpStream = this->rtpStream->FillBuffer(builder); - // Add currentSpatialLayer. - jsonObject["currentSpatialLayer"] = this->currentSpatialLayer; - - // Add preferredTemporalLayer. - jsonObject["preferredTemporalLayer"] = this->preferredTemporalLayer; - - // Add targetTemporalLayer. - jsonObject["targetTemporalLayer"] = this->targetTemporalLayer; + auto simulcastConsumerDump = FBS::Consumer::CreateSimulcastConsumerDump( + builder, + base, + rtpStream, + this->preferredSpatialLayer, + this->targetSpatialLayer, + this->currentSpatialLayer, + this->preferredTemporalLayer, + this->targetTemporalLayer, + this->encodingContext->GetCurrentTemporalLayer()); - // Add currentTemporalLayer. - jsonObject["currentTemporalLayer"] = this->encodingContext->GetCurrentTemporalLayer(); + return FBS::Consumer::CreateDumpResponse( + builder, + FBS::Consumer::DumpData::SimulcastConsumerDump, + simulcastConsumerDump.Union(), + FBS::RtpParameters::Type(this->type)); } - void SimulcastConsumer::FillJsonStats(json& jsonArray) const + flatbuffers::Offset SimulcastConsumer::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); + std::vector> rtpStreams; + // Add stats of our send stream. - jsonArray.emplace_back(json::value_t::object); - this->rtpStream->FillJsonStats(jsonArray[0]); + rtpStreams.emplace_back(this->rtpStream->FillBufferStats(builder)); - // Add stats of our recv stream. auto* producerCurrentRtpStream = GetProducerCurrentRtpStream(); + // Add stats of our recv stream. if (producerCurrentRtpStream) { - jsonArray.emplace_back(json::value_t::object); - producerCurrentRtpStream->FillJsonStats(jsonArray[1]); + rtpStreams.emplace_back(producerCurrentRtpStream->FillBufferStats(builder)); } + + return FBS::Consumer::CreateGetStatsResponseDirect(builder, &rtpStreams); } - void SimulcastConsumer::FillJsonScore(json& jsonObject) const + flatbuffers::Offset SimulcastConsumer::FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); @@ -197,23 +181,33 @@ namespace RTC auto* producerCurrentRtpStream = GetProducerCurrentRtpStream(); - jsonObject["score"] = this->rtpStream->GetScore(); + uint8_t producerScore{ 0 }; if (producerCurrentRtpStream) - jsonObject["producerScore"] = producerCurrentRtpStream->GetScore(); + producerScore = producerCurrentRtpStream->GetScore(); else - jsonObject["producerScore"] = 0; + producerScore = 0; - jsonObject["producerScores"] = *this->producerRtpStreamScores; + return FBS::Consumer::CreateConsumerScoreDirect( + builder, this->rtpStream->GetScore(), producerScore, this->producerRtpStreamScores); } void SimulcastConsumer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::CONSUMER_REQUEST_KEY_FRAME: + case Channel::ChannelRequest::Method::CONSUMER_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::FBS_Consumer_DumpResponse, dumpOffset); + + break; + } + + case Channel::ChannelRequest::Method::CONSUMER_REQUEST_KEY_FRAME: { if (IsActive()) RequestKeyFrames(); @@ -223,39 +217,24 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::CONSUMER_SET_PREFERRED_LAYERS: + case Channel::ChannelRequest::Method::CONSUMER_SET_PREFERRED_LAYERS: { auto previousPreferredSpatialLayer = this->preferredSpatialLayer; auto previousPreferredTemporalLayer = this->preferredTemporalLayer; - auto jsonSpatialLayerIt = request->data.find("spatialLayer"); - auto jsonTemporalLayerIt = request->data.find("temporalLayer"); + const auto* body = request->data->body_as(); + const auto* preferredLayers = body->preferredLayers(); // Spatial layer. - // clang-format off - if ( - jsonSpatialLayerIt == request->data.end() || - !Utils::Json::IsPositiveInteger(*jsonSpatialLayerIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing spatialLayer"); - } - - this->preferredSpatialLayer = jsonSpatialLayerIt->get(); + this->preferredSpatialLayer = preferredLayers->spatialLayer(); if (this->preferredSpatialLayer > this->rtpStream->GetSpatialLayers() - 1) this->preferredSpatialLayer = this->rtpStream->GetSpatialLayers() - 1; // preferredTemporaLayer is optional. - // clang-format off - if ( - jsonTemporalLayerIt != request->data.end() && - Utils::Json::IsPositiveInteger(*jsonTemporalLayerIt) - ) - // clang-format on + if (preferredLayers->temporalLayer().has_value()) { - this->preferredTemporalLayer = jsonTemporalLayerIt->get(); + this->preferredTemporalLayer = preferredLayers->temporalLayer().value(); if (this->preferredTemporalLayer > this->rtpStream->GetTemporalLayers() - 1) this->preferredTemporalLayer = this->rtpStream->GetTemporalLayers() - 1; @@ -271,12 +250,13 @@ namespace RTC this->preferredTemporalLayer, this->id.c_str()); - json data = json::object(); - - data["spatialLayer"] = this->preferredSpatialLayer; - data["temporalLayer"] = this->preferredTemporalLayer; + const flatbuffers::Optional preferredTemporalLayer{ this->preferredTemporalLayer }; + auto preferredLayersOffset = FBS::Consumer::CreateConsumerLayers( + request->GetBufferBuilder(), this->preferredSpatialLayer, preferredTemporalLayer); + auto responseOffset = FBS::Consumer::CreateSetPreferredLayersResponse( + request->GetBufferBuilder(), preferredLayersOffset); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_Consumer_SetPreferredLayersResponse, responseOffset); // clang-format off if ( @@ -1501,11 +1481,16 @@ namespace RTC { MS_TRACE(); - json data = json::object(); + auto scoreOffset = FillBufferScore(this->shared->channelNotifier->GetBufferBuilder()); - FillJsonScore(data); + auto notificationOffset = FBS::Consumer::CreateScoreNotification( + this->shared->channelNotifier->GetBufferBuilder(), scoreOffset); - this->shared->channelNotifier->Emit(this->id, "score", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::CONSUMER_SCORE, + FBS::Notification::Body::FBS_Consumer_ScoreNotification, + notificationOffset); } inline void SimulcastConsumer::EmitLayersChange() const @@ -1518,19 +1503,24 @@ namespace RTC this->encodingContext->GetCurrentTemporalLayer(), this->id.c_str()); - json data = json::object(); + flatbuffers::Offset layersOffset; if (this->currentSpatialLayer >= 0) { - data["spatialLayer"] = this->currentSpatialLayer; - data["temporalLayer"] = this->encodingContext->GetCurrentTemporalLayer(); - } - else - { - data = nullptr; + layersOffset = FBS::Consumer::CreateConsumerLayers( + this->shared->channelNotifier->GetBufferBuilder(), + this->currentSpatialLayer, + this->encodingContext->GetCurrentTemporalLayer()); } - this->shared->channelNotifier->Emit(this->id, "layerschange", data); + auto notificationOffset = FBS::Consumer::CreateLayersChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), layersOffset); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::CONSUMER_LAYERS_CHANGE, + FBS::Notification::Body::FBS_Consumer_LayersChangeNotification, + notificationOffset); } inline RTC::RtpStream* SimulcastConsumer::GetProducerCurrentRtpStream() const diff --git a/worker/src/RTC/SvcConsumer.cpp b/worker/src/RTC/SvcConsumer.cpp index d2b6af9566..af791de3e5 100644 --- a/worker/src/RTC/SvcConsumer.cpp +++ b/worker/src/RTC/SvcConsumer.cpp @@ -22,7 +22,7 @@ namespace RTC const std::string& id, const std::string& producerId, RTC::Consumer::Listener* listener, - json& data) + const FBS::Transport::ConsumeRequest* data) : RTC::Consumer::Consumer(shared, id, producerId, listener, data, RTC::RtpParameters::Type::SVC) { MS_TRACE(); @@ -37,38 +37,17 @@ namespace RTC if (encoding.spatialLayers < 2u && encoding.temporalLayers < 2u) MS_THROW_TYPE_ERROR("invalid number of layers"); - auto jsonPreferredLayersIt = data.find("preferredLayers"); - // Set preferredLayers (if given). - if (jsonPreferredLayersIt != data.end() && jsonPreferredLayersIt->is_object()) + if (flatbuffers::IsFieldPresent(data, FBS::Transport::ConsumeRequest::VT_PREFERREDLAYERS)) { - auto jsonSpatialLayerIt = jsonPreferredLayersIt->find("spatialLayer"); - auto jsonTemporalLayerIt = jsonPreferredLayersIt->find("temporalLayer"); - - // clang-format off - if ( - jsonSpatialLayerIt == jsonPreferredLayersIt->end() || - !Utils::Json::IsPositiveInteger(*jsonSpatialLayerIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing preferredLayers.spatialLayer"); - } - - this->preferredSpatialLayer = jsonSpatialLayerIt->get(); + this->preferredSpatialLayer = data->preferredLayers()->spatialLayer(); if (this->preferredSpatialLayer > encoding.spatialLayers - 1) this->preferredSpatialLayer = encoding.spatialLayers - 1; - // clang-format off - if ( - jsonTemporalLayerIt != jsonPreferredLayersIt->end() && - Utils::Json::IsPositiveInteger(*jsonTemporalLayerIt) - ) - // clang-format on + if (flatbuffers::IsFieldPresent( + data->preferredLayers(), FBS::Consumer::ConsumerLayers::VT_TEMPORALLAYER)) { - this->preferredTemporalLayer = jsonTemporalLayerIt->get(); - if (this->preferredTemporalLayer > encoding.temporalLayers - 1) this->preferredTemporalLayer = encoding.temporalLayers - 1; } @@ -110,8 +89,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelNotificationHandler*/ nullptr); } SvcConsumer::~SvcConsumer() @@ -123,74 +101,87 @@ namespace RTC delete this->rtpStream; } - void SvcConsumer::FillJson(json& jsonObject) const + flatbuffers::Offset SvcConsumer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); // Call the parent method. - RTC::Consumer::FillJson(jsonObject); - + auto base = RTC::Consumer::FillBuffer(builder); // Add rtpStream. - this->rtpStream->FillJson(jsonObject["rtpStream"]); - - // Add preferredSpatialLayer. - jsonObject["preferredSpatialLayer"] = this->preferredSpatialLayer; - - // Add targetSpatialLayer. - jsonObject["targetSpatialLayer"] = this->encodingContext->GetTargetSpatialLayer(); - - // Add currentSpatialLayer. - jsonObject["currentSpatialLayer"] = this->encodingContext->GetCurrentSpatialLayer(); - - // Add preferredTemporalLayer. - jsonObject["preferredTemporalLayer"] = this->preferredTemporalLayer; - - // Add targetTemporalLayer. - jsonObject["targetTemporalLayer"] = this->encodingContext->GetTargetTemporalLayer(); - - // Add currentTemporalLayer. - jsonObject["currentTemporalLayer"] = this->encodingContext->GetCurrentTemporalLayer(); + auto rtpStream = this->rtpStream->FillBuffer(builder); + + auto svcConsumerDump = FBS::Consumer::CreateSvcConsumerDump( + builder, + base, + rtpStream, + this->preferredSpatialLayer, + this->encodingContext->GetTargetSpatialLayer(), + this->encodingContext->GetCurrentSpatialLayer(), + this->preferredTemporalLayer, + this->encodingContext->GetTargetTemporalLayer(), + this->encodingContext->GetCurrentTemporalLayer()); + + return FBS::Consumer::CreateDumpResponse( + builder, + FBS::Consumer::DumpData::SvcConsumerDump, + svcConsumerDump.Union(), + FBS::RtpParameters::Type(this->type)); } - void SvcConsumer::FillJsonStats(json& jsonArray) const + flatbuffers::Offset SvcConsumer::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); + std::vector> rtpStreams; + // Add stats of our send stream. - jsonArray.emplace_back(json::value_t::object); - this->rtpStream->FillJsonStats(jsonArray[0]); + rtpStreams.emplace_back(this->rtpStream->FillBufferStats(builder)); // Add stats of our recv stream. if (this->producerRtpStream) { - jsonArray.emplace_back(json::value_t::object); - this->producerRtpStream->FillJsonStats(jsonArray[1]); + rtpStreams.emplace_back(producerRtpStream->FillBufferStats(builder)); } + + return FBS::Consumer::CreateGetStatsResponseDirect(builder, &rtpStreams); } - void SvcConsumer::FillJsonScore(json& jsonObject) const + flatbuffers::Offset SvcConsumer::FillBufferScore( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); MS_ASSERT(this->producerRtpStreamScores, "producerRtpStreamScores not set"); - jsonObject["score"] = this->rtpStream->GetScore(); + uint8_t producerScore{ 0 }; if (this->producerRtpStream) - jsonObject["producerScore"] = this->producerRtpStream->GetScore(); + producerScore = this->producerRtpStream->GetScore(); else - jsonObject["producerScore"] = 0; + producerScore = 0; - jsonObject["producerScores"] = *this->producerRtpStreamScores; + return FBS::Consumer::CreateConsumerScoreDirect( + builder, this->rtpStream->GetScore(), producerScore, this->producerRtpStreamScores); } void SvcConsumer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::CONSUMER_REQUEST_KEY_FRAME: + case Channel::ChannelRequest::Method::CONSUMER_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::FBS_Consumer_DumpResponse, dumpOffset); + + break; + } + + case Channel::ChannelRequest::Method::CONSUMER_REQUEST_KEY_FRAME: { if (IsActive()) RequestKeyFrame(); @@ -200,39 +191,24 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::CONSUMER_SET_PREFERRED_LAYERS: + case Channel::ChannelRequest::Method::CONSUMER_SET_PREFERRED_LAYERS: { auto previousPreferredSpatialLayer = this->preferredSpatialLayer; auto previousPreferredTemporalLayer = this->preferredTemporalLayer; - auto jsonSpatialLayerIt = request->data.find("spatialLayer"); - auto jsonTemporalLayerIt = request->data.find("temporalLayer"); + const auto* body = request->data->body_as(); + const auto* preferredLayers = body->preferredLayers(); // Spatial layer. - // clang-format off - if ( - jsonSpatialLayerIt == request->data.end() || - !Utils::Json::IsPositiveInteger(*jsonSpatialLayerIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing spatialLayer"); - } - - this->preferredSpatialLayer = jsonSpatialLayerIt->get(); + this->preferredSpatialLayer = preferredLayers->spatialLayer(); if (this->preferredSpatialLayer > this->rtpStream->GetSpatialLayers() - 1) this->preferredSpatialLayer = this->rtpStream->GetSpatialLayers() - 1; // preferredTemporaLayer is optional. - // clang-format off - if ( - jsonTemporalLayerIt != request->data.end() && - Utils::Json::IsPositiveInteger(*jsonTemporalLayerIt) - ) - // clang-format on + if (preferredLayers->temporalLayer().has_value()) { - this->preferredTemporalLayer = jsonTemporalLayerIt->get(); + this->preferredTemporalLayer = preferredLayers->temporalLayer().value(); if (this->preferredTemporalLayer > this->rtpStream->GetTemporalLayers() - 1) this->preferredTemporalLayer = this->rtpStream->GetTemporalLayers() - 1; @@ -248,12 +224,13 @@ namespace RTC this->preferredTemporalLayer, this->id.c_str()); - json data = json::object(); - - data["spatialLayer"] = this->preferredSpatialLayer; - data["temporalLayer"] = this->preferredTemporalLayer; + const flatbuffers::Optional preferredTemporalLayer{ this->preferredTemporalLayer }; + auto preferredLayersOffset = FBS::Consumer::CreateConsumerLayers( + request->GetBufferBuilder(), this->preferredSpatialLayer, preferredTemporalLayer); + auto responseOffset = FBS::Consumer::CreateSetPreferredLayersResponse( + request->GetBufferBuilder(), preferredLayersOffset); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_Consumer_SetPreferredLayersResponse, responseOffset); // clang-format off if ( @@ -1139,11 +1116,16 @@ namespace RTC { MS_TRACE(); - json data = json::object(); + auto scoreOffset = FillBufferScore(this->shared->channelNotifier->GetBufferBuilder()); - FillJsonScore(data); + auto notificationOffset = FBS::Consumer::CreateScoreNotification( + this->shared->channelNotifier->GetBufferBuilder(), scoreOffset); - this->shared->channelNotifier->Emit(this->id, "score", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::CONSUMER_SCORE, + FBS::Notification::Body::FBS_Consumer_ScoreNotification, + notificationOffset); } inline void SvcConsumer::EmitLayersChange() const @@ -1156,19 +1138,24 @@ namespace RTC this->encodingContext->GetCurrentTemporalLayer(), this->id.c_str()); - json data = json::object(); + flatbuffers::Offset layersOffset; if (this->encodingContext->GetCurrentSpatialLayer() >= 0) { - data["spatialLayer"] = this->encodingContext->GetCurrentSpatialLayer(); - data["temporalLayer"] = this->encodingContext->GetCurrentTemporalLayer(); - } - else - { - data = nullptr; + layersOffset = FBS::Consumer::CreateConsumerLayers( + this->shared->channelNotifier->GetBufferBuilder(), + this->encodingContext->GetCurrentSpatialLayer(), + this->encodingContext->GetCurrentTemporalLayer()); } - this->shared->channelNotifier->Emit(this->id, "layerschange", data); + auto notificationOffset = FBS::Consumer::CreateLayersChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), layersOffset); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::CONSUMER_LAYERS_CHANGE, + FBS::Notification::Body::FBS_Consumer_LayersChangeNotification, + notificationOffset); } inline void SvcConsumer::OnRtpStreamScore( diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index 65e0b57c73..5c14bfba63 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -5,6 +5,7 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "Utils.hpp" +#include "FBS/transport_generated.h" #include "RTC/BweType.hpp" #include "RTC/PipeConsumer.hpp" #include "RTC/RTCP/FeedbackPs.hpp" @@ -30,148 +31,70 @@ namespace RTC /* Instance methods. */ - Transport::Transport(RTC::Shared* shared, const std::string& id, Listener* listener, json& data) + Transport::Transport( + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::Transport::Options* options) : id(id), shared(shared), listener(listener), recvRtxTransmission(1000u), sendRtxTransmission(1000u), sendProbationTransmission(100u) { MS_TRACE(); - auto jsonDirectIt = data.find("direct"); - - // clang-format off - if ( - jsonDirectIt != data.end() && - jsonDirectIt->is_boolean() && - jsonDirectIt->get() - ) - // clang-format on + if (options->direct()) { - this->direct = true; - - auto jsonMaxMessageSizeIt = data.find("maxMessageSize"); - - // maxMessageSize is mandatory for direct Transports. - // clang-format off - if ( - jsonMaxMessageSizeIt == data.end() || - !Utils::Json::IsPositiveInteger(*jsonMaxMessageSizeIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("wrong maxMessageSize (not a number)"); - } - - this->maxMessageSize = jsonMaxMessageSizeIt->get(); + this->direct = true; + this->maxMessageSize = options->maxMessageSize(); } - auto jsonInitialAvailableOutgoingBitrateIt = data.find("initialAvailableOutgoingBitrate"); + this->initialAvailableOutgoingBitrate = options->initialAvailableOutgoingBitrate(); - if (jsonInitialAvailableOutgoingBitrateIt != data.end()) - { - if (!Utils::Json::IsPositiveInteger(*jsonInitialAvailableOutgoingBitrateIt)) - { - MS_THROW_TYPE_ERROR("wrong initialAvailableOutgoingBitrate (not a number)"); - } - - this->initialAvailableOutgoingBitrate = jsonInitialAvailableOutgoingBitrateIt->get(); - } - - auto jsonEnableSctpIt = data.find("enableSctp"); - - // clang-format off - if ( - jsonEnableSctpIt != data.end() && - jsonEnableSctpIt->is_boolean() && - jsonEnableSctpIt->get() - ) - // clang-format on + if (options->enableSctp()) { if (this->direct) { MS_THROW_TYPE_ERROR("cannot enable SCTP in a direct Transport"); } - auto jsonNumSctpStreamsIt = data.find("numSctpStreams"); - auto jsonMaxSctpMessageSizeIt = data.find("maxSctpMessageSize"); - auto jsonSctpSendBufferSizeIt = data.find("sctpSendBufferSize"); - auto jsonIsDataChannelIt = data.find("isDataChannel"); - // numSctpStreams is mandatory. - // clang-format off - if ( - jsonNumSctpStreamsIt == data.end() || - !jsonNumSctpStreamsIt->is_object() - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("wrong numSctpStreams (not an object)"); - } - - auto jsonOSIt = jsonNumSctpStreamsIt->find("OS"); - auto jsonMISIt = jsonNumSctpStreamsIt->find("MIS"); - - // numSctpStreams.OS and numSctpStreams.MIS are mandatory. - // clang-format off - if ( - jsonOSIt == jsonNumSctpStreamsIt->end() || - !Utils::Json::IsPositiveInteger(*jsonOSIt) || - jsonMISIt == jsonNumSctpStreamsIt->end() || - !Utils::Json::IsPositiveInteger(*jsonMISIt) - ) - // clang-format on + if (!flatbuffers::IsFieldPresent(options, FBS::Transport::Options::VT_NUMSCTPSTREAMS)) { - MS_THROW_TYPE_ERROR("wrong numSctpStreams.OS and/or numSctpStreams.MIS (not a number)"); + MS_THROW_TYPE_ERROR("numSctpStreams missing"); } - auto os = jsonOSIt->get(); - auto mis = jsonMISIt->get(); - // maxSctpMessageSize is mandatory. - // clang-format off - if ( - jsonMaxSctpMessageSizeIt == data.end() || - !Utils::Json::IsPositiveInteger(*jsonMaxSctpMessageSizeIt) - ) - // clang-format on + if (!flatbuffers::IsFieldPresent(options, FBS::Transport::Options::VT_MAXSCTPMESSAGESIZE)) { - MS_THROW_TYPE_ERROR("wrong maxSctpMessageSize (not a number)"); + MS_THROW_TYPE_ERROR("maxSctpMessageSize missing"); } - this->maxMessageSize = jsonMaxSctpMessageSizeIt->get(); + this->maxMessageSize = options->maxSctpMessageSize(); size_t sctpSendBufferSize; // sctpSendBufferSize is optional. - if (jsonSctpSendBufferSizeIt != data.end()) + if (flatbuffers::IsFieldPresent(options, FBS::Transport::Options::VT_SCTPSENDBUFFERSIZE)) { - if (!Utils::Json::IsPositiveInteger(*jsonSctpSendBufferSizeIt)) - { - MS_THROW_TYPE_ERROR("wrong sctpSendBufferSize (not a number)"); - } - - sctpSendBufferSize = jsonSctpSendBufferSizeIt->get(); - - if (sctpSendBufferSize > MaxSctpSendBufferSize) + if (options->sctpSendBufferSize() > MaxSctpSendBufferSize) { MS_THROW_TYPE_ERROR("wrong sctpSendBufferSize (maximum value exceeded)"); } + + sctpSendBufferSize = options->sctpSendBufferSize(); } else { sctpSendBufferSize = DefaultSctpSendBufferSize; } - // isDataChannel is optional. - bool isDataChannel{ false }; - - if (jsonIsDataChannelIt != data.end() && jsonIsDataChannelIt->is_boolean()) - { - isDataChannel = jsonIsDataChannelIt->get(); - } - // This may throw. this->sctpAssociation = new RTC::SctpAssociation( - this, os, mis, this->maxMessageSize, sctpSendBufferSize, isDataChannel); + this, + options->numSctpStreams()->os(), + options->numSctpStreams()->mis(), + this->maxMessageSize, + sctpSendBufferSize, + options->isDataChannel()); } // Create the RTCP timer. @@ -303,189 +226,184 @@ namespace RTC this->listener->OnTransportListenServerClosed(this); } - void Transport::FillJson(json& jsonObject) const + flatbuffers::Offset Transport::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add id. - jsonObject["id"] = this->id; - - // Add direct. - jsonObject["direct"] = this->direct; - // Add producerIds. - jsonObject["producerIds"] = json::array(); - auto jsonProducerIdsIt = jsonObject.find("producerIds"); + std::vector> producerIds; for (const auto& kv : this->mapProducers) { const auto& producerId = kv.first; - jsonProducerIdsIt->emplace_back(producerId); + producerIds.emplace_back(builder.CreateString(producerId)); } // Add consumerIds. - jsonObject["consumerIds"] = json::array(); - auto jsonConsumerIdsIt = jsonObject.find("consumerIds"); + std::vector> consumerIds; for (const auto& kv : this->mapConsumers) { const auto& consumerId = kv.first; - jsonConsumerIdsIt->emplace_back(consumerId); + consumerIds.emplace_back(builder.CreateString(consumerId)); } // Add mapSsrcConsumerId. - jsonObject["mapSsrcConsumerId"] = json::object(); - auto jsonMapSsrcConsumerId = jsonObject.find("mapSsrcConsumerId"); + std::vector> mapSsrcConsumerId; for (const auto& kv : this->mapSsrcConsumer) { auto ssrc = kv.first; auto* consumer = kv.second; - (*jsonMapSsrcConsumerId)[std::to_string(ssrc)] = consumer->id; + mapSsrcConsumerId.emplace_back( + FBS::Common::CreateUint32StringDirect(builder, ssrc, consumer->id.c_str())); } // Add mapRtxSsrcConsumerId. - jsonObject["mapRtxSsrcConsumerId"] = json::object(); - auto jsonMapRtxSsrcConsumerId = jsonObject.find("mapRtxSsrcConsumerId"); + std::vector> mapRtxSsrcConsumerId; for (const auto& kv : this->mapRtxSsrcConsumer) { auto ssrc = kv.first; auto* consumer = kv.second; - (*jsonMapRtxSsrcConsumerId)[std::to_string(ssrc)] = consumer->id; + mapRtxSsrcConsumerId.emplace_back( + FBS::Common::CreateUint32StringDirect(builder, ssrc, consumer->id.c_str())); } // Add dataProducerIds. - jsonObject["dataProducerIds"] = json::array(); - auto jsonDataProducerIdsIt = jsonObject.find("dataProducerIds"); + std::vector> dataProducerIds; for (const auto& kv : this->mapDataProducers) { const auto& dataProducerId = kv.first; - jsonDataProducerIdsIt->emplace_back(dataProducerId); + dataProducerIds.emplace_back(builder.CreateString(dataProducerId)); } // Add dataConsumerIds. - jsonObject["dataConsumerIds"] = json::array(); - auto jsonDataConsumerIdsIt = jsonObject.find("dataConsumerIds"); + std::vector> dataConsumerIds; for (const auto& kv : this->mapDataConsumers) { const auto& dataConsumerId = kv.first; - jsonDataConsumerIdsIt->emplace_back(dataConsumerId); + dataConsumerIds.emplace_back(builder.CreateString(dataConsumerId)); } // Add headerExtensionIds. - jsonObject["recvRtpHeaderExtensions"] = json::object(); - auto jsonRtpHeaderExtensionsIt = jsonObject.find("recvRtpHeaderExtensions"); + std::vector> recvRtpHeaderExtensions; if (this->recvRtpHeaderExtensionIds.mid != 0u) { - (*jsonRtpHeaderExtensionsIt)["mid"] = this->recvRtpHeaderExtensionIds.mid; + recvRtpHeaderExtensions.emplace_back( + FBS::Common::CreateStringUint8Direct(builder, "mid", this->recvRtpHeaderExtensionIds.mid)); } if (this->recvRtpHeaderExtensionIds.rid != 0u) { - (*jsonRtpHeaderExtensionsIt)["rid"] = this->recvRtpHeaderExtensionIds.rid; + recvRtpHeaderExtensions.emplace_back( + FBS::Common::CreateStringUint8Direct(builder, "rid", this->recvRtpHeaderExtensionIds.rid)); } if (this->recvRtpHeaderExtensionIds.rrid != 0u) { - (*jsonRtpHeaderExtensionsIt)["rrid"] = this->recvRtpHeaderExtensionIds.rrid; + recvRtpHeaderExtensions.emplace_back(FBS::Common::CreateStringUint8Direct( + builder, "rrid", this->recvRtpHeaderExtensionIds.rrid)); } if (this->recvRtpHeaderExtensionIds.absSendTime != 0u) { - (*jsonRtpHeaderExtensionsIt)["absSendTime"] = this->recvRtpHeaderExtensionIds.absSendTime; + recvRtpHeaderExtensions.emplace_back(FBS::Common::CreateStringUint8Direct( + builder, "absSendTime", this->recvRtpHeaderExtensionIds.absSendTime)); } if (this->recvRtpHeaderExtensionIds.transportWideCc01 != 0u) { - (*jsonRtpHeaderExtensionsIt)["transportWideCc01"] = - this->recvRtpHeaderExtensionIds.transportWideCc01; + recvRtpHeaderExtensions.emplace_back(FBS::Common::CreateStringUint8Direct( + builder, "transportWideCc01", this->recvRtpHeaderExtensionIds.transportWideCc01)); } - // Add rtpListener. - this->rtpListener.FillJson(jsonObject["rtpListener"]); + auto rtpListenerOffset = this->rtpListener.FillBuffer(builder); - // Add maxMessageSize. - jsonObject["maxMessageSize"] = this->maxMessageSize; + // Add sctpParameters. + flatbuffers::Offset sctpParameters; + // Add sctpState. + std::string sctpState; + // Add sctpListener. + flatbuffers::Offset sctpListener; if (this->sctpAssociation) { // Add sctpParameters. - this->sctpAssociation->FillJson(jsonObject["sctpParameters"]); + sctpParameters = this->sctpAssociation->FillBuffer(builder); - // Add sctpState. switch (this->sctpAssociation->GetState()) { case RTC::SctpAssociation::SctpState::NEW: - jsonObject["sctpState"] = "new"; + sctpState = "new"; break; case RTC::SctpAssociation::SctpState::CONNECTING: - jsonObject["sctpState"] = "connecting"; + sctpState = "connecting"; break; case RTC::SctpAssociation::SctpState::CONNECTED: - jsonObject["sctpState"] = "connected"; + sctpState = "connected"; break; case RTC::SctpAssociation::SctpState::FAILED: - jsonObject["sctpState"] = "failed"; + sctpState = "failed"; break; case RTC::SctpAssociation::SctpState::CLOSED: - jsonObject["sctpState"] = "closed"; + sctpState = "closed"; break; } - // Add sctpListener. - this->sctpListener.FillJson(jsonObject["sctpListener"]); + sctpListener = this->sctpListener.FillBuffer(builder); } // Add traceEventTypes. - std::vector traceEventTypes; - std::ostringstream traceEventTypesStream; + std::vector> traceEventTypes; if (this->traceEventTypes.probation) { - traceEventTypes.emplace_back("probation"); + traceEventTypes.emplace_back(builder.CreateString("probation")); } - if (this->traceEventTypes.bwe) { - traceEventTypes.emplace_back("bwe"); - } - - if (!traceEventTypes.empty()) - { - std::copy( - traceEventTypes.begin(), - traceEventTypes.end() - 1, - std::ostream_iterator(traceEventTypesStream, ",")); - traceEventTypesStream << traceEventTypes.back(); - } - - jsonObject["traceEventTypes"] = traceEventTypesStream.str(); + traceEventTypes.emplace_back(builder.CreateString("bwe")); + } + + return FBS::Transport::CreateDumpDirect( + builder, + this->id.c_str(), + this->direct, + &producerIds, + &consumerIds, + &mapSsrcConsumerId, + &mapRtxSsrcConsumerId, + &dataProducerIds, + &dataConsumerIds, + &recvRtpHeaderExtensions, + rtpListenerOffset, + this->maxMessageSize, + sctpParameters, + sctpState.c_str(), + sctpListener, + &traceEventTypes); } - void Transport::FillJsonStats(json& jsonArray) + flatbuffers::Offset Transport::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); auto nowMs = DepLibUV::GetTimeMs(); - jsonArray.emplace_back(json::value_t::object); - auto& jsonObject = jsonArray[0]; - - // Add transportId. - jsonObject["transportId"] = this->id; - - // Add timestamp. - jsonObject["timestamp"] = nowMs; + // Add sctpState. + std::string sctpState; if (this->sctpAssociation) { @@ -493,139 +411,86 @@ namespace RTC switch (this->sctpAssociation->GetState()) { case RTC::SctpAssociation::SctpState::NEW: - jsonObject["sctpState"] = "new"; + sctpState = "new"; break; case RTC::SctpAssociation::SctpState::CONNECTING: - jsonObject["sctpState"] = "connecting"; + sctpState = "connecting"; break; case RTC::SctpAssociation::SctpState::CONNECTED: - jsonObject["sctpState"] = "connected"; + sctpState = "connected"; break; case RTC::SctpAssociation::SctpState::FAILED: - jsonObject["sctpState"] = "failed"; + sctpState = "failed"; break; case RTC::SctpAssociation::SctpState::CLOSED: - jsonObject["sctpState"] = "closed"; + sctpState = "closed"; break; } } - // Add bytesReceived. - jsonObject["bytesReceived"] = this->recvTransmission.GetBytes(); - - // Add recvBitrate. - jsonObject["recvBitrate"] = this->recvTransmission.GetRate(nowMs); - - // Add bytesSent. - jsonObject["bytesSent"] = this->sendTransmission.GetBytes(); - - // Add sendBitrate. - jsonObject["sendBitrate"] = this->sendTransmission.GetRate(nowMs); - - // Add rtpBytesReceived. - jsonObject["rtpBytesReceived"] = this->recvRtpTransmission.GetBytes(); - - // Add rtpRecvBitrate. - jsonObject["rtpRecvBitrate"] = this->recvRtpTransmission.GetBitrate(nowMs); - - // Add rtpBytesSent. - jsonObject["rtpBytesSent"] = this->sendRtpTransmission.GetBytes(); - - // Add rtpSendBitrate. - jsonObject["rtpSendBitrate"] = this->sendRtpTransmission.GetBitrate(nowMs); - - // Add rtxBytesReceived. - jsonObject["rtxBytesReceived"] = this->recvRtxTransmission.GetBytes(); - - // Add rtxRecvBitrate. - jsonObject["rtxRecvBitrate"] = this->recvRtxTransmission.GetBitrate(nowMs); - - // Add rtxBytesSent. - jsonObject["rtxBytesSent"] = this->sendRtxTransmission.GetBytes(); - - // Add rtxSendBitrate. - jsonObject["rtxSendBitrate"] = this->sendRtxTransmission.GetBitrate(nowMs); - - // Add probationBytesSent. - jsonObject["probationBytesSent"] = this->sendProbationTransmission.GetBytes(); - - // Add probationSendBitrate. - jsonObject["probationSendBitrate"] = this->sendProbationTransmission.GetBitrate(nowMs); - - // Add availableOutgoingBitrate. - if (this->tccClient) - { - jsonObject["availableOutgoingBitrate"] = this->tccClient->GetAvailableBitrate(); - } - - // Add availableIncomingBitrate. - if (this->tccServer && this->tccServer->GetAvailableBitrate() != 0u) - { - jsonObject["availableIncomingBitrate"] = this->tccServer->GetAvailableBitrate(); - } - - // Add maxIncomingBitrate. - if (this->maxIncomingBitrate != 0u) - { - jsonObject["maxIncomingBitrate"] = this->maxIncomingBitrate; - } - - // Add packetLossReceived. - if (this->tccServer) - { - jsonObject["rtpPacketLossReceived"] = this->tccServer->GetPacketLoss(); - } - - // Add packetLossSent. - if (this->tccClient) - { - jsonObject["rtpPacketLossSent"] = this->tccClient->GetPacketLoss(); - } + return FBS::Transport::CreateStatsDirect( + builder, + // transportId. + this->id.c_str(), + // timestamp. + nowMs, + // sctpState. + sctpState.c_str(), + // bytesReceived. + this->recvTransmission.GetBytes(), + // recvBitrate. + this->recvTransmission.GetRate(nowMs), + // bytesSent. + this->sendTransmission.GetBytes(), + // sendBitrate. + this->sendTransmission.GetRate(nowMs), + // rtpBytesReceived. + this->recvRtpTransmission.GetBytes(), + // rtpRecvBitrate. + this->recvRtpTransmission.GetBitrate(nowMs), + // rtpBytesSent. + this->sendRtpTransmission.GetBytes(), + // rtpSendBitrate. + this->sendRtpTransmission.GetBitrate(nowMs), + // rtxBytesReceived. + this->recvRtxTransmission.GetBytes(), + // rtxRecvBitrate. + this->recvRtxTransmission.GetBitrate(nowMs), + // rtxBytesSent. + this->sendRtxTransmission.GetBytes(), + // rtxSendBitrate. + this->sendRtxTransmission.GetBitrate(nowMs), + // probationBytesSent. + this->sendProbationTransmission.GetBytes(), + // probationSendBitrate. + this->sendProbationTransmission.GetBitrate(nowMs), + // availableOutgoingBitrate. + this->tccClient ? this->tccClient->GetAvailableBitrate() : 0u, + // availableIncomingBitrate. + this->tccServer ? this->tccServer->GetAvailableBitrate() : 0u, + // maxIncomingBitrate. + this->maxIncomingBitrate, + // maxOutgoingBitrate. + this->maxOutgoingBitrate, + // minOutgoingBitrate. + this->minOutgoingBitrate, + // packetLossReceived. + this->tccServer ? this->tccServer->GetPacketLoss() : 0u, + // packetLossSent. + this->tccClient ? this->tccClient->GetPacketLoss() : 0u); } void Transport::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::TRANSPORT_DUMP: + case Channel::ChannelRequest::Method::TRANSPORT_SET_MAX_INCOMING_BITRATE: { - json data = json::object(); - - FillJson(data); - - request->Accept(data); + const auto* body = request->data->body_as(); - break; - } - - case Channel::ChannelRequest::MethodId::TRANSPORT_GET_STATS: - { - json data = json::array(); - - FillJsonStats(data); - - request->Accept(data); - - break; - } - - case Channel::ChannelRequest::MethodId::TRANSPORT_SET_MAX_INCOMING_BITRATE: - { - auto jsonBitrateIt = request->data.find("bitrate"); - - // clang-format off - if ( - jsonBitrateIt == request->data.end() || - !Utils::Json::IsPositiveInteger(*jsonBitrateIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing bitrate"); - } - - this->maxIncomingBitrate = jsonBitrateIt->get(); + this->maxIncomingBitrate = body->maxIncomingBitrate(); MS_DEBUG_TAG(bwe, "maximum incoming bitrate set to %" PRIu32, this->maxIncomingBitrate); @@ -639,21 +504,10 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_SET_MAX_OUTGOING_BITRATE: + case Channel::ChannelRequest::Method::TRANSPORT_SET_MAX_OUTGOING_BITRATE: { - auto jsonBitrateIt = request->data.find("bitrate"); - - // clang-format off - if ( - jsonBitrateIt == request->data.end() || - !Utils::Json::IsPositiveInteger(*jsonBitrateIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing bitrate"); - } - - const uint32_t bitrate = jsonBitrateIt->get(); + const auto* body = request->data->body_as(); + const uint32_t bitrate = body->maxOutgoingBitrate(); if (bitrate > 0u && bitrate < RTC::TransportCongestionControlMinOutgoingBitrate) { @@ -689,21 +543,10 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_SET_MIN_OUTGOING_BITRATE: + case Channel::ChannelRequest::Method::TRANSPORT_SET_MIN_OUTGOING_BITRATE: { - auto jsonBitrateIt = request->data.find("bitrate"); - - // clang-format off - if ( - jsonBitrateIt == request->data.end() || - !Utils::Json::IsPositiveInteger(*jsonBitrateIt) - ) - // clang-format on - { - MS_THROW_TYPE_ERROR("missing bitrate"); - } - - const uint32_t bitrate = jsonBitrateIt->get(); + const auto* body = request->data->body_as(); + const uint32_t bitrate = body->minOutgoingBitrate(); if (bitrate > 0u && bitrate < RTC::TransportCongestionControlMinOutgoingBitrate) { @@ -739,15 +582,18 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_PRODUCE: + case Channel::ChannelRequest::Method::TRANSPORT_PRODUCE: { - std::string producerId; + const auto* body = request->data->body_as(); + auto producerId = body->producerId()->str(); - // This may throw. - SetNewProducerIdFromData(request->data, producerId); + if (this->mapProducers.find(producerId) != this->mapProducers.end()) + { + MS_THROW_ERROR("a Producer with same producerId already exists"); + } // This may throw. - auto* producer = new RTC::Producer(this->shared, producerId, this, request->data); + auto* producer = new RTC::Producer(this->shared, producerId, this, body); // Insert the Producer into the RtpListener. // This may throw. If so, delete the Producer and throw. @@ -815,11 +661,10 @@ namespace RTC } // Create status response. - json data = json::object(); - - data["type"] = RTC::RtpParameters::GetTypeString(producer->GetType()); + auto responseOffset = FBS::Transport::CreateProduceResponse( + request->GetBufferBuilder(), FBS::RtpParameters::Type(producer->GetType())); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_Transport_ProduceResponse, responseOffset); // Check if TransportCongestionControlServer or REMB server must be // created. @@ -901,31 +746,18 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_CONSUME: + case Channel::ChannelRequest::Method::TRANSPORT_CONSUME: { - auto jsonProducerIdIt = request->data.find("producerId"); - - if (jsonProducerIdIt == request->data.end() || !jsonProducerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing producerId"); - } - - std::string producerId = jsonProducerIdIt->get(); - std::string consumerId; - - // This may throw. - SetNewConsumerIdFromData(request->data, consumerId); + const auto* body = request->data->body_as(); + const std::string producerId = body->producerId()->str(); + const std::string consumerId = body->consumerId()->str(); - // Get type. - auto jsonTypeIt = request->data.find("type"); - - if (jsonTypeIt == request->data.end() || !jsonTypeIt->is_string()) + if (this->mapConsumers.find(consumerId) != this->mapConsumers.end()) { - MS_THROW_TYPE_ERROR("missing type"); + MS_THROW_ERROR("a Consumer with same consumerId already exists"); } - // This may throw. - auto type = RTC::RtpParameters::GetType(jsonTypeIt->get()); + auto type = RTC::RtpParameters::Type(body->type()); RTC::Consumer* consumer{ nullptr }; @@ -941,8 +773,7 @@ namespace RTC case RTC::RtpParameters::Type::SIMPLE: { // This may throw. - consumer = - new RTC::SimpleConsumer(this->shared, consumerId, producerId, this, request->data); + consumer = new RTC::SimpleConsumer(this->shared, consumerId, producerId, this, body); break; } @@ -950,8 +781,7 @@ namespace RTC case RTC::RtpParameters::Type::SIMULCAST: { // This may throw. - consumer = - new RTC::SimulcastConsumer(this->shared, consumerId, producerId, this, request->data); + consumer = new RTC::SimulcastConsumer(this->shared, consumerId, producerId, this, body); break; } @@ -959,8 +789,7 @@ namespace RTC case RTC::RtpParameters::Type::SVC: { // This may throw. - consumer = - new RTC::SvcConsumer(this->shared, consumerId, producerId, this, request->data); + consumer = new RTC::SvcConsumer(this->shared, consumerId, producerId, this, body); break; } @@ -968,8 +797,7 @@ namespace RTC case RTC::RtpParameters::Type::PIPE: { // This may throw. - consumer = - new RTC::PipeConsumer(this->shared, consumerId, producerId, this, request->data); + consumer = new RTC::PipeConsumer(this->shared, consumerId, producerId, this, body); break; } @@ -1004,23 +832,25 @@ namespace RTC MS_DEBUG_DEV( "Consumer created [consumerId:%s, producerId:%s]", consumerId.c_str(), producerId.c_str()); - // Create status response. - json data = json::object(); - - data["paused"] = consumer->IsPaused(); - data["producerPaused"] = consumer->IsProducerPaused(); - - consumer->FillJsonScore(data["score"]); - + flatbuffers::Offset preferredLayersOffset; auto preferredLayers = consumer->GetPreferredLayers(); if (preferredLayers.spatial > -1 && preferredLayers.temporal > -1) { - data["preferredLayers"]["spatialLayer"] = preferredLayers.spatial; - data["preferredLayers"]["temporalLayer"] = preferredLayers.temporal; + const flatbuffers::Optional preferredTemporalLayer{ preferredLayers.temporal }; + preferredLayersOffset = FBS::Consumer::CreateConsumerLayers( + request->GetBufferBuilder(), preferredLayers.spatial, preferredTemporalLayer); } - request->Accept(data); + auto scoreOffset = consumer->FillBufferScore(request->GetBufferBuilder()); + auto responseOffset = FBS::Transport::CreateConsumeResponse( + request->GetBufferBuilder(), + consumer->IsPaused(), + consumer->IsProducerPaused(), + scoreOffset, + preferredLayersOffset); + + request->Accept(FBS::Response::Body::FBS_Transport_ConsumeResponse, responseOffset); // Check if Transport Congestion Control client must be created. const auto& rtpHeaderExtensionIds = consumer->GetRtpHeaderExtensionIds(); @@ -1038,19 +868,19 @@ namespace RTC // - there is "transport-cc" in codecs RTCP feedback. // // clang-format off - if ( - consumer->GetKind() == RTC::Media::Kind::VIDEO && - rtpHeaderExtensionIds.transportWideCc01 != 0u && - std::any_of( - codecs.begin(), codecs.end(), [](const RTC::RtpCodecParameters& codec) - { - return std::any_of( - codec.rtcpFeedback.begin(), codec.rtcpFeedback.end(), [](const RTC::RtcpFeedback& fb) + if ( + consumer->GetKind() == RTC::Media::Kind::VIDEO && + rtpHeaderExtensionIds.transportWideCc01 != 0u && + std::any_of( + codecs.begin(), codecs.end(), [](const RTC::RtpCodecParameters& codec) { - return fb.type == "transport-cc"; - }); - }) - ) + return std::any_of( + codec.rtcpFeedback.begin(), codec.rtcpFeedback.end(), [](const RTC::RtcpFeedback& fb) + { + return fb.type == "transport-cc"; + }); + }) + ) // clang-format on { MS_DEBUG_TAG(bwe, "enabling TransportCongestionControlClient with transport-cc"); @@ -1064,19 +894,19 @@ namespace RTC // - there is "remb" in codecs RTCP feedback. // // clang-format off - else if ( - consumer->GetKind() == RTC::Media::Kind::VIDEO && - rtpHeaderExtensionIds.absSendTime != 0u && - std::any_of( - codecs.begin(), codecs.end(), [](const RTC::RtpCodecParameters& codec) - { - return std::any_of( - codec.rtcpFeedback.begin(), codec.rtcpFeedback.end(), [](const RTC::RtcpFeedback& fb) + else if ( + consumer->GetKind() == RTC::Media::Kind::VIDEO && + rtpHeaderExtensionIds.absSendTime != 0u && + std::any_of( + codecs.begin(), codecs.end(), [](const RTC::RtpCodecParameters& codec) { - return fb.type == "goog-remb"; - }); - }) - ) + return std::any_of( + codec.rtcpFeedback.begin(), codec.rtcpFeedback.end(), [](const RTC::RtcpFeedback& fb) + { + return fb.type == "goog-remb"; + }); + }) + ) // clang-format on { MS_DEBUG_TAG(bwe, "enabling TransportCongestionControlClient with REMB"); @@ -1124,20 +954,20 @@ namespace RTC // - there is "transport-cc" in codecs RTCP feedback. // // clang-format off - if ( - !this->senderBwe && - consumer->GetKind() == RTC::Media::Kind::VIDEO && - rtpHeaderExtensionIds.transportWideCc01 != 0u && - std::any_of( - codecs.begin(), codecs.end(), [](const RTC::RtpCodecParameters& codec) - { - return std::any_of( - codec.rtcpFeedback.begin(), codec.rtcpFeedback.end(), [](const RTC::RtcpFeedback& fb) + if ( + !this->senderBwe && + consumer->GetKind() == RTC::Media::Kind::VIDEO && + rtpHeaderExtensionIds.transportWideCc01 != 0u && + std::any_of( + codecs.begin(), codecs.end(), [](const RTC::RtpCodecParameters& codec) { - return fb.type == "transport-cc"; - }); - }) - ) + return std::any_of( + codec.rtcpFeedback.begin(), codec.rtcpFeedback.end(), [](const RTC::RtcpFeedback& fb) + { + return fb.type == "transport-cc"; + }); + }) + ) // clang-format on { MS_DEBUG_TAG(bwe, "enabling SenderBandwidthEstimator"); @@ -1175,7 +1005,7 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_PRODUCE_DATA: + case Channel::ChannelRequest::Method::TRANSPORT_PRODUCE_DATA: { // Early check. The Transport must support SCTP or be direct. if (!this->sctpAssociation && !this->direct) @@ -1183,14 +1013,16 @@ namespace RTC MS_THROW_ERROR("SCTP not enabled and not a direct Transport"); } - std::string dataProducerId; + const auto* body = request->data->body_as(); + + auto dataProducerId = body->dataProducerId()->str(); // This may throw. - SetNewDataProducerIdFromData(request->data, dataProducerId); + CheckNoDataProducer(dataProducerId); // This may throw. - auto* dataProducer = new RTC::DataProducer( - this->shared, dataProducerId, this->maxMessageSize, this, request->data); + auto* dataProducer = + new RTC::DataProducer(this->shared, dataProducerId, this->maxMessageSize, this, body); // Verify the type of the DataProducer. switch (dataProducer->GetType()) @@ -1263,16 +1095,14 @@ namespace RTC MS_DEBUG_DEV("DataProducer created [dataProducerId:%s]", dataProducerId.c_str()); - json data = json::object(); - - dataProducer->FillJson(data); + auto dumpOffset = dataProducer->FillBuffer(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_DataProducer_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_CONSUME_DATA: + case Channel::ChannelRequest::Method::TRANSPORT_CONSUME_DATA: { // Early check. The Transport must support SCTP or be direct. if (!this->sctpAssociation && !this->direct) @@ -1280,18 +1110,13 @@ namespace RTC MS_THROW_ERROR("SCTP not enabled and not a direct Transport"); } - auto jsonDataProducerIdIt = request->data.find("dataProducerId"); + const auto* body = request->data->body_as(); - if (jsonDataProducerIdIt == request->data.end() || !jsonDataProducerIdIt->is_string()) - { - MS_THROW_ERROR("missing dataProducerId"); - } - - std::string dataProducerId = jsonDataProducerIdIt->get(); - std::string dataConsumerId; + auto dataProducerId = body->dataProducerId()->str(); + auto dataConsumerId = body->dataConsumerId()->str(); // This may throw. - SetNewDataConsumerIdFromData(request->data, dataConsumerId); + CheckNoDataConsumer(dataConsumerId); // This may throw. auto* dataConsumer = new RTC::DataConsumer( @@ -1300,7 +1125,7 @@ namespace RTC dataProducerId, this->sctpAssociation, this, - request->data, + body, this->maxMessageSize); // Verify the type of the DataConsumer. @@ -1356,11 +1181,9 @@ namespace RTC dataConsumerId.c_str(), dataProducerId.c_str()); - json data = json::object(); - - dataConsumer->FillJson(data); + auto dumpOffset = dataConsumer->FillBuffer(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_DataConsumer_DumpResponse, dumpOffset); if (IsConnected()) { @@ -1381,33 +1204,22 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_ENABLE_TRACE_EVENT: + case Channel::ChannelRequest::Method::TRANSPORT_ENABLE_TRACE_EVENT: { - auto jsonTypesIt = request->data.find("types"); - - // Disable all if no entries. - if (jsonTypesIt == request->data.end() || !jsonTypesIt->is_array()) - { - MS_THROW_TYPE_ERROR("wrong types (not an array)"); - } + const auto* body = request->data->body_as(); // Reset traceEventTypes. struct TraceEventTypes newTraceEventTypes; - for (const auto& type : *jsonTypesIt) + for (const auto& type : *body->events()) { - if (!type.is_string()) - { - MS_THROW_TYPE_ERROR("wrong type (not a string)"); - } - - const std::string typeStr = type.get(); + const auto typeStr = type->str(); if (typeStr == "probation") { newTraceEventTypes.probation = true; } - if (typeStr == "bwe") + else if (typeStr == "bwe") { newTraceEventTypes.bwe = true; } @@ -1420,10 +1232,12 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_CLOSE_PRODUCER: + case Channel::ChannelRequest::Method::TRANSPORT_CLOSE_PRODUCER: { + const auto* body = request->data->body_as(); + // This may throw. - RTC::Producer* producer = GetProducerFromData(request->data); + RTC::Producer* producer = GetProducerById(body->producerId()->str()); // Remove it from the RtpListener. this->rtpListener.RemoveProducer(producer); @@ -1457,10 +1271,12 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_CLOSE_CONSUMER: + case Channel::ChannelRequest::Method::TRANSPORT_CLOSE_CONSUMER: { + const auto* body = request->data->body_as(); + // This may throw. - RTC::Consumer* consumer = GetConsumerFromData(request->data); + RTC::Consumer* consumer = GetConsumerById(body->consumerId()->str()); // Remove it from the maps. this->mapConsumers.erase(consumer->id); @@ -1501,10 +1317,12 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_CLOSE_DATA_PRODUCER: + case Channel::ChannelRequest::Method::TRANSPORT_CLOSE_DATA_PRODUCER: { + const auto* body = request->data->body_as(); + // This may throw. - RTC::DataProducer* dataProducer = GetDataProducerFromData(request->data); + RTC::DataProducer* dataProducer = GetDataProducerById(body->dataProducerId()->str()); if (dataProducer->GetType() == RTC::DataProducer::Type::SCTP) { @@ -1534,10 +1352,12 @@ namespace RTC break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_CLOSE_DATA_CONSUMER: + case Channel::ChannelRequest::Method::TRANSPORT_CLOSE_DATA_CONSUMER: { + const auto* body = request->data->body_as(); + // This may throw. - RTC::DataConsumer* dataConsumer = GetDataConsumerFromData(request->data); + RTC::DataConsumer* dataConsumer = GetDataConsumerById(body->dataConsumerId()->str()); // Remove it from the maps. this->mapDataConsumers.erase(dataConsumer->id); @@ -1563,33 +1383,30 @@ namespace RTC default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } - } - void Transport::HandleRequest(PayloadChannel::PayloadChannelRequest* request) - { - MS_TRACE(); + return; - switch (request->methodId) + switch (request->method) { default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_ERROR("unknown method"); } } } - void Transport::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) + void Transport::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); - switch (notification->eventId) + switch (notification->event) { default: { - MS_ERROR("unknown event '%s'", notification->event.c_str()); + MS_ERROR("unknown event '%s'", notification->eventCStr); } } } @@ -1789,88 +1606,50 @@ namespace RTC this->sctpAssociation->ProcessSctpData(data, len); } - void Transport::SetNewProducerIdFromData(json& data, std::string& producerId) const + void Transport::CheckNoDataProducer(const std::string& dataProducerId) const { - MS_TRACE(); - - auto jsonProducerIdIt = data.find("producerId"); - - if (jsonProducerIdIt == data.end() || !jsonProducerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing producerId"); - } - - producerId.assign(jsonProducerIdIt->get()); - - if (this->mapProducers.find(producerId) != this->mapProducers.end()) + if (this->mapDataProducers.find(dataProducerId) != this->mapDataProducers.end()) { - MS_THROW_ERROR("a Producer with same producerId already exists"); + MS_THROW_ERROR("a DataProducer with same dataProducerId already exists"); } } - RTC::Producer* Transport::GetProducerFromData(json& data) const + void Transport::CheckNoDataConsumer(const std::string& dataConsumerId) const { MS_TRACE(); - auto jsonProducerIdIt = data.find("producerId"); - - if (jsonProducerIdIt == data.end() || !jsonProducerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing producerId"); - } - - auto it = this->mapProducers.find(jsonProducerIdIt->get()); - - if (it == this->mapProducers.end()) + if (this->mapDataConsumers.find(dataConsumerId) != this->mapDataConsumers.end()) { - MS_THROW_ERROR("Producer not found"); + MS_THROW_ERROR("a DataConsumer with same dataConsumerId already exists"); } - - RTC::Producer* producer = it->second; - - return producer; } - void Transport::SetNewConsumerIdFromData(json& data, std::string& consumerId) const + RTC::Producer* Transport::GetProducerById(const std::string& producerId) const { MS_TRACE(); - auto jsonConsumerIdIt = data.find("consumerId"); + auto it = this->mapProducers.find(producerId); - if (jsonConsumerIdIt == data.end() || !jsonConsumerIdIt->is_string()) + if (it == this->mapProducers.end()) { - MS_THROW_TYPE_ERROR("missing consumerId"); + MS_THROW_ERROR("Producer not found"); } - consumerId.assign(jsonConsumerIdIt->get()); - - if (this->mapConsumers.find(consumerId) != this->mapConsumers.end()) - { - MS_THROW_ERROR("a Consumer with same consumerId already exists"); - } + return it->second; } - RTC::Consumer* Transport::GetConsumerFromData(json& data) const + RTC::Consumer* Transport::GetConsumerById(const std::string& consumerId) const { MS_TRACE(); - auto jsonConsumerIdIt = data.find("consumerId"); - - if (jsonConsumerIdIt == data.end() || !jsonConsumerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing consumerId"); - } - - auto it = this->mapConsumers.find(jsonConsumerIdIt->get()); + auto it = this->mapConsumers.find(consumerId); if (it == this->mapConsumers.end()) { MS_THROW_ERROR("Consumer not found"); } - RTC::Consumer* consumer = it->second; - - return consumer; + return it->second; } inline RTC::Consumer* Transport::GetConsumerByMediaSsrc(uint32_t ssrc) const @@ -1905,88 +1684,32 @@ namespace RTC return consumer; } - void Transport::SetNewDataProducerIdFromData(json& data, std::string& dataProducerId) const + RTC::DataProducer* Transport::GetDataProducerById(const std::string& dataProducerId) const { MS_TRACE(); - auto jsonDataProducerIdIt = data.find("dataProducerId"); - - if (jsonDataProducerIdIt == data.end() || !jsonDataProducerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing dataProducerId"); - } - - dataProducerId.assign(jsonDataProducerIdIt->get()); - - if (this->mapDataProducers.find(dataProducerId) != this->mapDataProducers.end()) - { - MS_THROW_ERROR("a DataProducer with same dataProducerId already exists"); - } - } - - RTC::DataProducer* Transport::GetDataProducerFromData(json& data) const - { - MS_TRACE(); - - auto jsonDataProducerIdIt = data.find("dataProducerId"); - - if (jsonDataProducerIdIt == data.end() || !jsonDataProducerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing dataProducerId"); - } - - auto it = this->mapDataProducers.find(jsonDataProducerIdIt->get()); + auto it = this->mapDataProducers.find(dataProducerId); if (it == this->mapDataProducers.end()) { MS_THROW_ERROR("DataProducer not found"); } - RTC::DataProducer* dataProducer = it->second; - - return dataProducer; - } - - void Transport::SetNewDataConsumerIdFromData(json& data, std::string& dataConsumerId) const - { - MS_TRACE(); - - auto jsonDataConsumerIdIt = data.find("dataConsumerId"); - - if (jsonDataConsumerIdIt == data.end() || !jsonDataConsumerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing dataConsumerId"); - } - - dataConsumerId.assign(jsonDataConsumerIdIt->get()); - - if (this->mapDataConsumers.find(dataConsumerId) != this->mapDataConsumers.end()) - { - MS_THROW_ERROR("a DataConsumer with same dataConsumerId already exists"); - } + return it->second; } - RTC::DataConsumer* Transport::GetDataConsumerFromData(json& data) const + RTC::DataConsumer* Transport::GetDataConsumerById(const std::string& dataConsumerId) const { MS_TRACE(); - auto jsonDataConsumerIdIt = data.find("dataConsumerId"); - - if (jsonDataConsumerIdIt == data.end() || !jsonDataConsumerIdIt->is_string()) - { - MS_THROW_TYPE_ERROR("missing dataConsumerId"); - } - - auto it = this->mapDataConsumers.find(jsonDataConsumerIdIt->get()); + auto it = this->mapDataConsumers.find(dataConsumerId); if (it == this->mapDataConsumers.end()) { MS_THROW_ERROR("DataConsumer not found"); } - RTC::DataConsumer* dataConsumer = it->second; - - return dataConsumer; + return it->second; } void Transport::HandleRtcpPacket(RTC::RTCP::Packet* packet) @@ -2555,15 +2278,17 @@ namespace RTC return; } - json data = json::object(); - - data["type"] = "probation"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "out"; + auto notification = FBS::Transport::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Transport::TraceType::PROBATION, + DepLibUV::GetTimeMs(), + FBS::Transport::TraceDirection::DIRECTION_OUT); - packet->FillJson(data["info"]); - - this->shared->channelNotifier->Emit(this->id, "trace", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::TRANSPORT_TRACE, + FBS::Notification::Body::FBS_Transport_TraceNotification, + notification); } inline void Transport::EmitTraceEventBweType( @@ -2576,30 +2301,32 @@ namespace RTC return; } - json data = json::object(); - - data["type"] = "bwe"; - data["timestamp"] = DepLibUV::GetTimeMs(); - data["direction"] = "out"; - data["info"]["desiredBitrate"] = bitrates.desiredBitrate; - data["info"]["effectiveDesiredBitrate"] = bitrates.effectiveDesiredBitrate; - data["info"]["minBitrate"] = bitrates.minBitrate; - data["info"]["maxBitrate"] = bitrates.maxBitrate; - data["info"]["startBitrate"] = bitrates.startBitrate; - data["info"]["maxPaddingBitrate"] = bitrates.maxPaddingBitrate; - data["info"]["availableBitrate"] = bitrates.availableBitrate; - - switch (this->tccClient->GetBweType()) - { - case RTC::BweType::TRANSPORT_CC: - data["info"]["type"] = "transport-cc"; - break; - case RTC::BweType::REMB: - data["info"]["type"] = "remb"; - break; - } - - this->shared->channelNotifier->Emit(this->id, "trace", data); + auto traceInfo = FBS::Transport::CreateBweTraceInfo( + this->shared->channelNotifier->GetBufferBuilder(), + bitrates.desiredBitrate, + bitrates.effectiveDesiredBitrate, + bitrates.minBitrate, + bitrates.maxBitrate, + bitrates.startBitrate, + bitrates.maxPaddingBitrate, + bitrates.availableBitrate, + this->tccClient->GetBweType() == RTC::BweType::TRANSPORT_CC + ? FBS::Transport::BweType::TRANSPORT_CC + : FBS::Transport::BweType::REMB); + + auto notification = FBS::Transport::CreateTraceNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::Transport::TraceType::BWE, + DepLibUV::GetTimeMs(), + FBS::Transport::TraceDirection::DIRECTION_OUT, + FBS::Transport::TraceInfo::BweTraceInfo, + traceInfo.Union()); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::TRANSPORT_TRACE, + FBS::Notification::Body::FBS_Transport_TraceNotification, + notification); } inline void Transport::OnProducerPaused(RTC::Producer* producer) @@ -2962,11 +2689,14 @@ namespace RTC MS_TRACE(); // Notify the Node Transport. - json data = json::object(); - - data["sctpState"] = "connecting"; - - this->shared->channelNotifier->Emit(this->id, "sctpstatechange", data); + auto sctpStateChangeOffset = FBS::Transport::CreateSctpStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::SctpAssociation::SctpState::CONNECTING); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::TRANSPORT_SCTP_STATE_CHANGE, + FBS::Notification::Body::FBS_Transport_SctpStateChangeNotification, + sctpStateChangeOffset); } inline void Transport::OnSctpAssociationConnected(RTC::SctpAssociation* /*sctpAssociation*/) @@ -2985,11 +2715,14 @@ namespace RTC } // Notify the Node Transport. - json data = json::object(); - - data["sctpState"] = "connected"; - - this->shared->channelNotifier->Emit(this->id, "sctpstatechange", data); + auto sctpStateChangeOffset = FBS::Transport::CreateSctpStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::SctpAssociation::SctpState::CONNECTED); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::TRANSPORT_SCTP_STATE_CHANGE, + FBS::Notification::Body::FBS_Transport_SctpStateChangeNotification, + sctpStateChangeOffset); } inline void Transport::OnSctpAssociationFailed(RTC::SctpAssociation* /*sctpAssociation*/) @@ -3008,11 +2741,14 @@ namespace RTC } // Notify the Node Transport. - json data = json::object(); - - data["sctpState"] = "failed"; - - this->shared->channelNotifier->Emit(this->id, "sctpstatechange", data); + auto sctpStateChangeOffset = FBS::Transport::CreateSctpStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::SctpAssociation::SctpState::FAILED); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::TRANSPORT_SCTP_STATE_CHANGE, + FBS::Notification::Body::FBS_Transport_SctpStateChangeNotification, + sctpStateChangeOffset); } inline void Transport::OnSctpAssociationClosed(RTC::SctpAssociation* /*sctpAssociation*/) @@ -3031,11 +2767,14 @@ namespace RTC } // Notify the Node Transport. - json data = json::object(); - - data["sctpState"] = "closed"; - - this->shared->channelNotifier->Emit(this->id, "sctpstatechange", data); + auto sctpStateChangeOffset = FBS::Transport::CreateSctpStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::SctpAssociation::SctpState::CLOSED); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::TRANSPORT_SCTP_STATE_CHANGE, + FBS::Notification::Body::FBS_Transport_SctpStateChangeNotification, + sctpStateChangeOffset); } inline void Transport::OnSctpAssociationSendData( diff --git a/worker/src/RTC/TransportTuple.cpp b/worker/src/RTC/TransportTuple.cpp index ab8dce24b2..4150b2f7e0 100644 --- a/worker/src/RTC/TransportTuple.cpp +++ b/worker/src/RTC/TransportTuple.cpp @@ -9,44 +9,40 @@ namespace RTC { /* Instance methods. */ - void TransportTuple::FillJson(json& jsonObject) const + flatbuffers::Offset TransportTuple::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); int family; - std::string ip; - uint16_t port; - - Utils::IP::GetAddressInfo(GetLocalAddress(), family, ip, port); + std::string localIp; + uint16_t localPort; - // Add localIp. - if (this->localAnnouncedIp.empty()) - jsonObject["localIp"] = ip; - else - jsonObject["localIp"] = this->localAnnouncedIp; + Utils::IP::GetAddressInfo(GetLocalAddress(), family, localIp, localPort); - // Add localPort. - jsonObject["localPort"] = port; + localIp = this->localAnnouncedIp.empty() ? localIp : this->localAnnouncedIp; - Utils::IP::GetAddressInfo(GetRemoteAddress(), family, ip, port); + std::string remoteIp; + uint16_t remotePort; - // Add remoteIp. - jsonObject["remoteIp"] = ip; + Utils::IP::GetAddressInfo(GetRemoteAddress(), family, remoteIp, remotePort); - // Add remotePort. - jsonObject["remotePort"] = port; + std::string protocol; // Add protocol. switch (GetProtocol()) { case Protocol::UDP: - jsonObject["protocol"] = "udp"; + protocol = "udp"; break; case Protocol::TCP: - jsonObject["protocol"] = "tcp"; + protocol = "tcp"; break; } + + return FBS::Transport::CreateTupleDirect( + builder, localIp.c_str(), localPort, remoteIp.c_str(), remotePort, protocol.c_str()); } void TransportTuple::Dump() const diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index fab070a96c..8e3cf849e2 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -27,113 +27,58 @@ namespace RTC /* Instance methods. */ - WebRtcServer::WebRtcServer(RTC::Shared* shared, const std::string& id, json& data) + WebRtcServer::WebRtcServer( + RTC::Shared* shared, + const std::string& id, + const flatbuffers::Vector>* listenInfos) : id(id), shared(shared) { MS_TRACE(); - auto jsonListenInfosIt = data.find("listenInfos"); - - if (jsonListenInfosIt == data.end()) - MS_THROW_TYPE_ERROR("missing listenInfos"); - else if (!jsonListenInfosIt->is_array()) - MS_THROW_TYPE_ERROR("wrong listenInfos (not an array)"); - else if (jsonListenInfosIt->empty()) + if (listenInfos->size() == 0) MS_THROW_TYPE_ERROR("wrong listenInfos (empty array)"); - else if (jsonListenInfosIt->size() > 8) + else if (listenInfos->size() > 8) MS_THROW_TYPE_ERROR("wrong listenInfos (too many entries)"); - std::vector listenInfos(jsonListenInfosIt->size()); - - for (size_t i{ 0 }; i < jsonListenInfosIt->size(); ++i) + try { - auto& jsonListenInfo = (*jsonListenInfosIt)[i]; - auto& listenInfo = listenInfos[i]; - - if (!jsonListenInfo.is_object()) - MS_THROW_TYPE_ERROR("wrong listenInfo (not an object)"); - - auto jsonProtocolIt = jsonListenInfo.find("protocol"); - - if (jsonProtocolIt == jsonListenInfo.end()) - MS_THROW_TYPE_ERROR("missing listenInfo.protocol"); - else if (!jsonProtocolIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenInfo.protocol (not an string"); - - std::string protocolStr = jsonProtocolIt->get(); - - Utils::String::ToLowerCase(protocolStr); - - if (protocolStr == "udp") - listenInfo.protocol = RTC::TransportTuple::Protocol::UDP; - else if (protocolStr == "tcp") - listenInfo.protocol = RTC::TransportTuple::Protocol::TCP; - else - MS_THROW_TYPE_ERROR("invalid listenInfo.protocol (must be 'udp' or 'tcp'"); - - auto jsonIpIt = jsonListenInfo.find("ip"); - - if (jsonIpIt == jsonListenInfo.end()) - MS_THROW_TYPE_ERROR("missing listenInfo.ip"); - else if (!jsonIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenInfo.ip (not an string"); - - listenInfo.ip.assign(jsonIpIt->get()); - - // This may throw. - Utils::IP::NormalizeIp(listenInfo.ip); - - auto jsonAnnouncedIpIt = jsonListenInfo.find("announcedIp"); - - if (jsonAnnouncedIpIt != jsonListenInfo.end()) + for (const auto* listenInfo : *listenInfos) { - if (!jsonAnnouncedIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenInfo.announcedIp (not an string)"); + auto ip = listenInfo->ip()->str(); - listenInfo.announcedIp.assign(jsonAnnouncedIpIt->get()); - } + // This may throw. + Utils::IP::NormalizeIp(ip); - uint16_t port{ 0 }; - auto jsonPortIt = jsonListenInfo.find("port"); + std::string announcedIp; - if (jsonPortIt != jsonListenInfo.end()) - { - if (!(jsonPortIt->is_number() && Utils::Json::IsPositiveInteger(*jsonPortIt))) - MS_THROW_TYPE_ERROR("wrong port (not a positive number)"); - - port = jsonPortIt->get(); - } - - listenInfo.port = port; - } + if (flatbuffers::IsFieldPresent(listenInfo, FBS::WebRtcServer::ListenInfo::VT_ANNOUNCEDIP)) + { + announcedIp = listenInfo->announcedIp()->str(); + } - try - { - for (auto& listenInfo : listenInfos) - { - if (listenInfo.protocol == RTC::TransportTuple::Protocol::UDP) + if (listenInfo->protocol() == FBS::Transport::Protocol::UDP) { // This may throw. RTC::UdpSocket* udpSocket; - if (listenInfo.port != 0) - udpSocket = new RTC::UdpSocket(this, listenInfo.ip, listenInfo.port); + if (listenInfo->port() != 0) + udpSocket = new RTC::UdpSocket(this, ip, listenInfo->port()); else - udpSocket = new RTC::UdpSocket(this, listenInfo.ip); + udpSocket = new RTC::UdpSocket(this, ip); - this->udpSocketOrTcpServers.emplace_back(udpSocket, nullptr, listenInfo.announcedIp); + this->udpSocketOrTcpServers.emplace_back(udpSocket, nullptr, announcedIp); } - else if (listenInfo.protocol == RTC::TransportTuple::Protocol::TCP) + else if (listenInfo->protocol() == FBS::Transport::Protocol::TCP) { // This may throw. RTC::TcpServer* tcpServer; - if (listenInfo.port != 0) - tcpServer = new RTC::TcpServer(this, this, listenInfo.ip, listenInfo.port); + if (listenInfo->port() != 0) + tcpServer = new RTC::TcpServer(this, this, ip, listenInfo->port()); else - tcpServer = new RTC::TcpServer(this, this, listenInfo.ip); + tcpServer = new RTC::TcpServer(this, this, ip); - this->udpSocketOrTcpServers.emplace_back(nullptr, tcpServer, listenInfo.announcedIp); + this->udpSocketOrTcpServers.emplace_back(nullptr, tcpServer, announcedIp); } } @@ -141,8 +86,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ nullptr, - /*payloadChannelNotificationHandler*/ nullptr); + /*channelNotificationHandler*/ nullptr); } catch (const MediaSoupError& error) { @@ -185,120 +129,89 @@ namespace RTC this->webRtcTransports.clear(); } - void WebRtcServer::FillJson(json& jsonObject) const + flatbuffers::Offset WebRtcServer::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Add id. - jsonObject["id"] = this->id; - // Add udpSockets and tcpServers. - jsonObject["udpSockets"] = json::array(); - auto jsonUdpSocketsIt = jsonObject.find("udpSockets"); - jsonObject["tcpServers"] = json::array(); - auto jsonTcpServersIt = jsonObject.find("tcpServers"); - - size_t udpSocketIdx{ 0 }; - size_t tcpServerIdx{ 0 }; + std::vector> udpSockets; + std::vector> tcpServers; - for (auto& item : this->udpSocketOrTcpServers) + for (const auto& item : this->udpSocketOrTcpServers) { if (item.udpSocket) { - jsonUdpSocketsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonUdpSocketsIt)[udpSocketIdx]; - - jsonEntry["ip"] = item.udpSocket->GetLocalIp(); - jsonEntry["port"] = item.udpSocket->GetLocalPort(); - - ++udpSocketIdx; + udpSockets.emplace_back(FBS::WebRtcServer::CreateIpPortDirect( + builder, item.udpSocket->GetLocalIp().c_str(), item.udpSocket->GetLocalPort())); } else if (item.tcpServer) { - jsonTcpServersIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonTcpServersIt)[tcpServerIdx]; - - jsonEntry["ip"] = item.tcpServer->GetLocalIp(); - jsonEntry["port"] = item.tcpServer->GetLocalPort(); - - ++tcpServerIdx; + tcpServers.emplace_back(FBS::WebRtcServer::CreateIpPortDirect( + builder, item.tcpServer->GetLocalIp().c_str(), item.tcpServer->GetLocalPort())); } } // Add webRtcTransportIds. - jsonObject["webRtcTransportIds"] = json::array(); - auto jsonWebRtcTransportIdsIt = jsonObject.find("webRtcTransportIds"); + std::vector> webRtcTransportIds; for (auto* webRtcTransport : this->webRtcTransports) { - jsonWebRtcTransportIdsIt->emplace_back(webRtcTransport->id); + webRtcTransportIds.emplace_back(builder.CreateString(webRtcTransport->id)); } - size_t idx; - // Add localIceUsernameFragments. - jsonObject["localIceUsernameFragments"] = json::array(); - auto jsonLocalIceUsernamesIt = jsonObject.find("localIceUsernameFragments"); + std::vector> localIceUsernameFragments; - idx = 0; - for (auto& kv : this->mapLocalIceUsernameFragmentWebRtcTransport) + for (const auto& kv : this->mapLocalIceUsernameFragmentWebRtcTransport) { const auto& localIceUsernameFragment = kv.first; const auto* webRtcTransport = kv.second; - jsonLocalIceUsernamesIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonLocalIceUsernamesIt)[idx]; - - jsonEntry["localIceUsernameFragment"] = localIceUsernameFragment; - jsonEntry["webRtcTransportId"] = webRtcTransport->id; - - ++idx; + localIceUsernameFragments.emplace_back(FBS::WebRtcServer::CreateIceUserNameFragmentDirect( + builder, localIceUsernameFragment.c_str(), webRtcTransport->id.c_str())); } // Add tupleHashes. - jsonObject["tupleHashes"] = json::array(); - auto jsonTupleHashesIt = jsonObject.find("tupleHashes"); + std::vector> tupleHashes; - idx = 0; - for (auto& kv : this->mapTupleWebRtcTransport) + for (const auto& kv : this->mapTupleWebRtcTransport) { const auto& tupleHash = kv.first; const auto* webRtcTransport = kv.second; - jsonTupleHashesIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonTupleHashesIt)[idx]; - - jsonEntry["tupleHash"] = tupleHash; - jsonEntry["webRtcTransportId"] = webRtcTransport->id; - - ++idx; + tupleHashes.emplace_back( + FBS::WebRtcServer::CreateTupleHashDirect(builder, tupleHash, webRtcTransport->id.c_str())); } + + return FBS::WebRtcServer::CreateDumpResponseDirect( + builder, + this->id.c_str(), + &udpSockets, + &tcpServers, + &webRtcTransportIds, + &localIceUsernameFragments, + &tupleHashes); } void WebRtcServer::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::WEBRTC_SERVER_DUMP: + case Channel::ChannelRequest::Method::WEBRTC_SERVER_DUMP: { - json data = json::object(); - - FillJson(data); + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_WebRtcServer_DumpResponse, dumpOffset); break; } default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } } diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index 4ec9065d50..5bc1a5c435 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -5,6 +5,7 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "Utils.hpp" +#include "FBS/webRtcTransport_generated.h" #include // std::pow() namespace RTC @@ -28,169 +29,91 @@ namespace RTC /* Instance methods. */ WebRtcTransport::WebRtcTransport( - RTC::Shared* shared, const std::string& id, RTC::Transport::Listener* listener, json& data) - : RTC::Transport::Transport(shared, id, listener, data) + RTC::Shared* shared, + const std::string& id, + RTC::Transport::Listener* listener, + const FBS::WebRtcTransport::WebRtcTransportOptions* options) + : RTC::Transport::Transport(shared, id, listener, options->base()) { MS_TRACE(); - bool enableUdp{ true }; - auto jsonEnableUdpIt = data.find("enableUdp"); - - if (jsonEnableUdpIt != data.end()) - { - if (!jsonEnableUdpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong enableUdp (not a boolean)"); - - enableUdp = jsonEnableUdpIt->get(); - } - - bool enableTcp{ false }; - auto jsonEnableTcpIt = data.find("enableTcp"); - - if (jsonEnableTcpIt != data.end()) - { - if (!jsonEnableTcpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong enableTcp (not a boolean)"); - - enableTcp = jsonEnableTcpIt->get(); - } - - bool preferUdp{ false }; - auto jsonPreferUdpIt = data.find("preferUdp"); - - if (jsonPreferUdpIt != data.end()) - { - if (!jsonPreferUdpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong preferUdp (not a boolean)"); - - preferUdp = jsonPreferUdpIt->get(); - } - - bool preferTcp{ false }; - auto jsonPreferTcpIt = data.find("preferTcp"); - - if (jsonPreferTcpIt != data.end()) - { - if (!jsonPreferTcpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong preferTcp (not a boolean)"); - - preferTcp = jsonPreferTcpIt->get(); - } - - auto jsonListenIpsIt = data.find("listenIps"); - - if (jsonListenIpsIt == data.end()) - MS_THROW_TYPE_ERROR("missing listenIps"); - else if (!jsonListenIpsIt->is_array()) - MS_THROW_TYPE_ERROR("wrong listenIps (not an array)"); - else if (jsonListenIpsIt->empty()) - MS_THROW_TYPE_ERROR("wrong listenIps (empty array)"); - else if (jsonListenIpsIt->size() > 8) - MS_THROW_TYPE_ERROR("wrong listenIps (too many IPs)"); - - std::vector listenIps(jsonListenIpsIt->size()); - - for (size_t i{ 0 }; i < jsonListenIpsIt->size(); ++i) - { - auto& jsonListenIp = (*jsonListenIpsIt)[i]; - auto& listenIp = listenIps[i]; - - if (!jsonListenIp.is_object()) - MS_THROW_TYPE_ERROR("wrong listenIp (not an object)"); - - auto jsonIpIt = jsonListenIp.find("ip"); - - if (jsonIpIt == jsonListenIp.end()) - MS_THROW_TYPE_ERROR("missing listenIp.ip"); - else if (!jsonIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenIp.ip (not an string"); - - listenIp.ip.assign(jsonIpIt->get()); - - // This may throw. - Utils::IP::NormalizeIp(listenIp.ip); - - auto jsonAnnouncedIpIt = jsonListenIp.find("announcedIp"); - - if (jsonAnnouncedIpIt != jsonListenIp.end()) - { - if (!jsonAnnouncedIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenIp.announcedIp (not an string)"); - - listenIp.announcedIp.assign(jsonAnnouncedIpIt->get()); - } - } - - uint16_t port{ 0 }; - auto jsonPortIt = data.find("port"); - - if (jsonPortIt != data.end()) - { - if (!(jsonPortIt->is_number() && Utils::Json::IsPositiveInteger(*jsonPortIt))) - MS_THROW_TYPE_ERROR("wrong port (not a positive number)"); - - port = jsonPortIt->get(); - } + const auto* listenInfo = options->listen_as(); + const auto* listenIps = listenInfo->listenIps(); try { uint16_t iceLocalPreferenceDecrement{ 0 }; - if (enableUdp && enableTcp) - this->iceCandidates.reserve(2 * jsonListenIpsIt->size()); + if (options->enableUdp() && options->enableTcp()) + this->iceCandidates.reserve(2 * listenIps->size()); else - this->iceCandidates.reserve(jsonListenIpsIt->size()); + this->iceCandidates.reserve(listenIps->size()); - for (auto& listenIp : listenIps) + for (const auto* listenIp : *listenIps) { - if (enableUdp) + auto ip = listenIp->ip()->str(); + + // This may throw. + Utils::IP::NormalizeIp(ip); + + if (options->enableUdp()) { uint16_t iceLocalPreference = IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement; - if (preferUdp) + if (options->preferUdp()) iceLocalPreference += 1000; uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); // This may throw. RTC::UdpSocket* udpSocket; - if (port != 0) - udpSocket = new RTC::UdpSocket(this, listenIp.ip, port); + if (listenInfo->port() != 0) + udpSocket = new RTC::UdpSocket(this, ip, listenInfo->port()); else - udpSocket = new RTC::UdpSocket(this, listenIp.ip); + udpSocket = new RTC::UdpSocket(this, ip); + + std::string announcedIp; - this->udpSockets[udpSocket] = listenIp.announcedIp; + if (flatbuffers::IsFieldPresent(listenIp, FBS::Transport::ListenIp::VT_ANNOUNCEDIP)) + announcedIp = listenIp->announcedIp()->str(); - if (listenIp.announcedIp.empty()) + this->udpSockets[udpSocket] = announcedIp; + + if (announcedIp.size() == 0) this->iceCandidates.emplace_back(udpSocket, icePriority); else - this->iceCandidates.emplace_back(udpSocket, icePriority, listenIp.announcedIp); + this->iceCandidates.emplace_back(udpSocket, icePriority, announcedIp); } - if (enableTcp) + if (options->enableTcp()) { uint16_t iceLocalPreference = IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement; - if (preferTcp) + if (options->preferTcp()) iceLocalPreference += 1000; - uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); + const uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); // This may throw. RTC::TcpServer* tcpServer; - if (port != 0) - tcpServer = new RTC::TcpServer(this, this, listenIp.ip, port); + if (listenInfo->port() != 0) + tcpServer = new RTC::TcpServer(this, this, ip, listenInfo->port()); else - tcpServer = new RTC::TcpServer(this, this, listenIp.ip); + tcpServer = new RTC::TcpServer(this, this, ip); - this->tcpServers[tcpServer] = listenIp.announcedIp; + std::string announcedIp; - if (listenIp.announcedIp.empty()) + if (flatbuffers::IsFieldPresent(listenIp, FBS::Transport::ListenIp::VT_ANNOUNCEDIP)) + announcedIp = listenIp->announcedIp()->str(); + + this->tcpServers[tcpServer] = announcedIp; + + if (announcedIp.size() == 0) this->iceCandidates.emplace_back(tcpServer, icePriority); else - this->iceCandidates.emplace_back(tcpServer, icePriority, listenIp.announcedIp); + this->iceCandidates.emplace_back(tcpServer, icePriority, announcedIp); } // Decrement initial ICE local preference for next IP. @@ -208,8 +131,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ this, - /*payloadChannelNotificationHandler*/ this); + /*channelNotificationHandler*/ this); } catch (const MediaSoupError& error) { @@ -252,8 +174,8 @@ namespace RTC RTC::Transport::Listener* listener, WebRtcTransportListener* webRtcTransportListener, std::vector& iceCandidates, - json& data) - : RTC::Transport::Transport(shared, id, listener, data), + const FBS::WebRtcTransport::WebRtcTransportOptions* options) + : RTC::Transport::Transport(shared, id, listener, options->base()), webRtcTransportListener(webRtcTransportListener), iceCandidates(iceCandidates) { MS_TRACE(); @@ -277,8 +199,7 @@ namespace RTC this->shared->channelMessageRegistrator->RegisterHandler( this->id, /*channelRequestHandler*/ this, - /*payloadChannelRequestHandler*/ this, - /*payloadChannelNotificationHandler*/ this); + /*channelNotificationHandler*/ this); } catch (const MediaSoupError& error) { @@ -339,250 +260,249 @@ namespace RTC this->webRtcTransportListener->OnWebRtcTransportClosed(this); } - void WebRtcTransport::FillJson(json& jsonObject) const + flatbuffers::Offset WebRtcTransport::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); - // Call the parent method. - RTC::Transport::FillJson(jsonObject); - - // Add iceRole (we are always "controlled"). - jsonObject["iceRole"] = "controlled"; - // Add iceParameters. - jsonObject["iceParameters"] = json::object(); - auto jsonIceParametersIt = jsonObject.find("iceParameters"); - - (*jsonIceParametersIt)["usernameFragment"] = this->iceServer->GetUsernameFragment(); - (*jsonIceParametersIt)["password"] = this->iceServer->GetPassword(); - (*jsonIceParametersIt)["iceLite"] = true; + auto iceParameters = FBS::WebRtcTransport::CreateIceParametersDirect( + builder, + this->iceServer->GetUsernameFragment().c_str(), + this->iceServer->GetPassword().c_str(), + true); - // Add iceCandidates. - jsonObject["iceCandidates"] = json::array(); - auto jsonIceCandidatesIt = jsonObject.find("iceCandidates"); + std::vector> iceCandidates; + iceCandidates.reserve(this->iceCandidates.size()); - for (size_t i{ 0 }; i < this->iceCandidates.size(); ++i) + for (const auto& iceCandidate : this->iceCandidates) { - jsonIceCandidatesIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonIceCandidatesIt)[i]; - const auto& iceCandidate = this->iceCandidates[i]; - - iceCandidate.FillJson(jsonEntry); + iceCandidates.emplace_back(iceCandidate.FillBuffer(builder)); } // Add iceState. + std::string iceState; + switch (this->iceServer->GetState()) { case RTC::IceServer::IceState::NEW: - jsonObject["iceState"] = "new"; + iceState = "new"; break; case RTC::IceServer::IceState::CONNECTED: - jsonObject["iceState"] = "connected"; + iceState = "connected"; break; case RTC::IceServer::IceState::COMPLETED: - jsonObject["iceState"] = "completed"; + iceState = "completed"; break; case RTC::IceServer::IceState::DISCONNECTED: - jsonObject["iceState"] = "disconnected"; + iceState = "disconnected"; break; } // Add iceSelectedTuple. - if (this->iceServer->GetSelectedTuple()) - this->iceServer->GetSelectedTuple()->FillJson(jsonObject["iceSelectedTuple"]); + flatbuffers::Offset iceSelectedTuple; - // Add dtlsParameters. - jsonObject["dtlsParameters"] = json::object(); - auto jsonDtlsParametersIt = jsonObject.find("dtlsParameters"); + if (this->iceServer->GetSelectedTuple()) + iceSelectedTuple = this->iceServer->GetSelectedTuple()->FillBuffer(builder); // Add dtlsParameters.fingerprints. - (*jsonDtlsParametersIt)["fingerprints"] = json::array(); - auto jsonDtlsParametersFingerprintsIt = jsonDtlsParametersIt->find("fingerprints"); - auto& fingerprints = this->dtlsTransport->GetLocalFingerprints(); + std::vector> fingerprints; - for (size_t i{ 0 }; i < fingerprints.size(); ++i) + for (const auto& fingerprint : this->dtlsTransport->GetLocalFingerprints()) { - jsonDtlsParametersFingerprintsIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonDtlsParametersFingerprintsIt)[i]; - auto& fingerprint = fingerprints[i]; + auto& algorithm = RTC::DtlsTransport::GetFingerprintAlgorithmString(fingerprint.algorithm); + const auto& value = fingerprint.value; - jsonEntry["algorithm"] = - RTC::DtlsTransport::GetFingerprintAlgorithmString(fingerprint.algorithm); - jsonEntry["value"] = fingerprint.value; + fingerprints.emplace_back( + FBS::WebRtcTransport::CreateFingerprintDirect(builder, algorithm.c_str(), value.c_str())); } // Add dtlsParameters.role. + std::string dtlsRole; + switch (this->dtlsRole) { case RTC::DtlsTransport::Role::NONE: - (*jsonDtlsParametersIt)["role"] = "none"; + dtlsRole = "none"; break; case RTC::DtlsTransport::Role::AUTO: - (*jsonDtlsParametersIt)["role"] = "auto"; + dtlsRole = "auto"; break; case RTC::DtlsTransport::Role::CLIENT: - (*jsonDtlsParametersIt)["role"] = "client"; + dtlsRole = "client"; break; case RTC::DtlsTransport::Role::SERVER: - (*jsonDtlsParametersIt)["role"] = "server"; + dtlsRole = "server"; break; } // Add dtlsState. + std::string dtlsState; + switch (this->dtlsTransport->GetState()) { case RTC::DtlsTransport::DtlsState::NEW: - jsonObject["dtlsState"] = "new"; + dtlsState = "new"; break; case RTC::DtlsTransport::DtlsState::CONNECTING: - jsonObject["dtlsState"] = "connecting"; + dtlsState = "connecting"; break; case RTC::DtlsTransport::DtlsState::CONNECTED: - jsonObject["dtlsState"] = "connected"; + dtlsState = "connected"; break; case RTC::DtlsTransport::DtlsState::FAILED: - jsonObject["dtlsState"] = "failed"; + dtlsState = "failed"; break; case RTC::DtlsTransport::DtlsState::CLOSED: - jsonObject["dtlsState"] = "closed"; + dtlsState = "closed"; break; } + + // Add base transport dump. + auto base = Transport::FillBuffer(builder); + // Add dtlsParameters. + auto dtlsParameters = + FBS::WebRtcTransport::CreateDtlsParametersDirect(builder, &fingerprints, dtlsRole.c_str()); + + return FBS::WebRtcTransport::CreateDumpResponseDirect( + builder, + base, + // iceRole (we are always "controlled"). + "controlled", + iceParameters, + &iceCandidates, + iceState.c_str(), + iceSelectedTuple, + dtlsParameters, + dtlsState.c_str()); } - void WebRtcTransport::FillJsonStats(json& jsonArray) + flatbuffers::Offset WebRtcTransport::FillBufferStats( + flatbuffers::FlatBufferBuilder& builder) { MS_TRACE(); - // Call the parent method. - RTC::Transport::FillJsonStats(jsonArray); - - auto& jsonObject = jsonArray[0]; - - // Add type. - jsonObject["type"] = "webrtc-transport"; - - // Add iceRole (we are always "controlled"). - jsonObject["iceRole"] = "controlled"; - // Add iceState. + std::string iceState; + switch (this->iceServer->GetState()) { case RTC::IceServer::IceState::NEW: - jsonObject["iceState"] = "new"; + iceState = "new"; break; case RTC::IceServer::IceState::CONNECTED: - jsonObject["iceState"] = "connected"; + iceState = "connected"; break; case RTC::IceServer::IceState::COMPLETED: - jsonObject["iceState"] = "completed"; + iceState = "completed"; break; case RTC::IceServer::IceState::DISCONNECTED: - jsonObject["iceState"] = "disconnected"; + iceState = "disconnected"; break; } + // Add iceSelectedTuple. + flatbuffers::Offset iceSelectedTuple; + if (this->iceServer->GetSelectedTuple()) - { - // Add iceSelectedTuple. - this->iceServer->GetSelectedTuple()->FillJson(jsonObject["iceSelectedTuple"]); - } + iceSelectedTuple = this->iceServer->GetSelectedTuple()->FillBuffer(builder); + + std::string dtlsState; // Add dtlsState. switch (this->dtlsTransport->GetState()) { case RTC::DtlsTransport::DtlsState::NEW: - jsonObject["dtlsState"] = "new"; + dtlsState = "new"; break; case RTC::DtlsTransport::DtlsState::CONNECTING: - jsonObject["dtlsState"] = "connecting"; + dtlsState = "connecting"; break; case RTC::DtlsTransport::DtlsState::CONNECTED: - jsonObject["dtlsState"] = "connected"; + dtlsState = "connected"; break; case RTC::DtlsTransport::DtlsState::FAILED: - jsonObject["dtlsState"] = "failed"; + dtlsState = "failed"; break; case RTC::DtlsTransport::DtlsState::CLOSED: - jsonObject["dtlsState"] = "closed"; + dtlsState = "closed"; break; } + + // Base Transport stats. + auto base = Transport::FillBufferStats(builder); + + return FBS::WebRtcTransport::CreateGetStatsResponseDirect( + builder, + base, + // iceRole (we are always "controlled"). + "controlled", + iceState.c_str(), + iceSelectedTuple, + dtlsState.c_str()); } void WebRtcTransport::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::TRANSPORT_CONNECT: + case Channel::ChannelRequest::Method::TRANSPORT_GET_STATS: + { + auto responseOffset = FillBufferStats(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::FBS_WebRtcTransport_GetStatsResponse, responseOffset); + + break; + } + + case Channel::ChannelRequest::Method::TRANSPORT_DUMP: + { + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); + + request->Accept(FBS::Response::Body::FBS_WebRtcTransport_DumpResponse, dumpOffset); + + break; + } + + case Channel::ChannelRequest::Method::WEBRTC_TRANSPORT_CONNECT: { // Ensure this method is not called twice. if (this->connectCalled) MS_THROW_ERROR("connect() already called"); + const auto* body = request->data->body_as(); + const auto* dtlsParameters = body->dtlsParameters(); + RTC::DtlsTransport::Fingerprint dtlsRemoteFingerprint; RTC::DtlsTransport::Role dtlsRemoteRole; - auto jsonDtlsParametersIt = request->data.find("dtlsParameters"); - - if (jsonDtlsParametersIt == request->data.end() || !jsonDtlsParametersIt->is_object()) - MS_THROW_TYPE_ERROR("missing dtlsParameters"); - - auto jsonFingerprintsIt = jsonDtlsParametersIt->find("fingerprints"); - - if (jsonFingerprintsIt == jsonDtlsParametersIt->end() || !jsonFingerprintsIt->is_array()) - { - MS_THROW_TYPE_ERROR("missing dtlsParameters.fingerprints"); - } - else if (jsonFingerprintsIt->empty()) + if (dtlsParameters->fingerprints()->size() == 0) { MS_THROW_TYPE_ERROR("empty dtlsParameters.fingerprints array"); } // NOTE: Just take the first fingerprint. - for (auto& jsonFingerprint : *jsonFingerprintsIt) + for (const auto& fingerprint : *dtlsParameters->fingerprints()) { - if (!jsonFingerprint.is_object()) - MS_THROW_TYPE_ERROR("wrong entry in dtlsParameters.fingerprints (not an object)"); - - auto jsonAlgorithmIt = jsonFingerprint.find("algorithm"); - - if (jsonAlgorithmIt == jsonFingerprint.end()) - MS_THROW_TYPE_ERROR("missing fingerprint.algorithm"); - else if (!jsonAlgorithmIt->is_string()) - MS_THROW_TYPE_ERROR("wrong fingerprint.algorithm (not a string)"); - dtlsRemoteFingerprint.algorithm = - RTC::DtlsTransport::GetFingerprintAlgorithm(jsonAlgorithmIt->get()); + RTC::DtlsTransport::GetFingerprintAlgorithm(fingerprint->algorithm()->str()); if (dtlsRemoteFingerprint.algorithm == RTC::DtlsTransport::FingerprintAlgorithm::NONE) { MS_THROW_TYPE_ERROR("invalid fingerprint.algorithm value"); } - auto jsonValueIt = jsonFingerprint.find("value"); - - if (jsonValueIt == jsonFingerprint.end()) - MS_THROW_TYPE_ERROR("missing fingerprint.value"); - else if (!jsonValueIt->is_string()) - MS_THROW_TYPE_ERROR("wrong fingerprint.value (not a string)"); - - dtlsRemoteFingerprint.value = jsonValueIt->get(); + dtlsRemoteFingerprint.value = fingerprint->value()->str(); // Just use the first fingerprint. break; } - auto jsonRoleIt = jsonDtlsParametersIt->find("role"); - - if (jsonRoleIt != jsonDtlsParametersIt->end()) + if (flatbuffers::IsFieldPresent(dtlsParameters, FBS::WebRtcTransport::DtlsParameters::VT_ROLE)) { - if (!jsonRoleIt->is_string()) - MS_THROW_TYPE_ERROR("wrong dtlsParameters.role (not a string)"); - - dtlsRemoteRole = RTC::DtlsTransport::StringToRole(jsonRoleIt->get()); + dtlsRemoteRole = RTC::DtlsTransport::StringToRole(dtlsParameters->role()->str()); if (dtlsRemoteRole == RTC::DtlsTransport::Role::NONE) MS_THROW_TYPE_ERROR("invalid dtlsParameters.role value"); @@ -625,28 +545,31 @@ namespace RTC } // Tell the caller about the selected local DTLS role. - json data = json::object(); + std::string dtlsLocalRole; switch (this->dtlsRole) { case RTC::DtlsTransport::Role::CLIENT: - data["dtlsLocalRole"] = "client"; + dtlsLocalRole = "client"; break; case RTC::DtlsTransport::Role::SERVER: - data["dtlsLocalRole"] = "server"; + dtlsLocalRole = "server"; break; default: MS_ABORT("invalid local DTLS role"); } - request->Accept(data); + auto responseOffset = FBS::WebRtcTransport::CreateConnectResponseDirect( + request->GetBufferBuilder(), dtlsLocalRole.c_str()); + + request->Accept(FBS::Response::Body::FBS_WebRtcTransport_ConnectResponse, responseOffset); break; } - case Channel::ChannelRequest::MethodId::TRANSPORT_RESTART_ICE: + case Channel::ChannelRequest::Method::TRANSPORT_RESTART_ICE: { const std::string usernameFragment = Utils::Crypto::GetRandomString(32); const std::string password = Utils::Crypto::GetRandomString(32); @@ -657,16 +580,14 @@ namespace RTC "WebRtcTransport ICE usernameFragment and password changed [id:%s]", this->id.c_str()); // Reply with the updated ICE local parameters. - json data = json::object(); - - data["iceParameters"] = json::object(); - auto jsonIceParametersIt = data.find("iceParameters"); + auto responseOffset = FBS::Transport::CreateRestartIceResponseDirect( + request->GetBufferBuilder(), + this->iceServer->GetUsernameFragment().c_str(), + this->iceServer->GetPassword().c_str(), + true /* iceLite */ + ); - (*jsonIceParametersIt)["usernameFragment"] = this->iceServer->GetUsernameFragment(); - (*jsonIceParametersIt)["password"] = this->iceServer->GetPassword(); - (*jsonIceParametersIt)["iceLite"] = true; - - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_Transport_RestartIceResponse, responseOffset); break; } @@ -679,7 +600,7 @@ namespace RTC } } - void WebRtcTransport::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) + void WebRtcTransport::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); @@ -1300,11 +1221,17 @@ namespace RTC MS_DEBUG_TAG(ice, "ICE selected tuple"); // Notify the Node WebRtcTransport. - json data = json::object(); + auto tuple = this->iceServer->GetSelectedTuple()->FillBuffer( + this->shared->channelNotifier->GetBufferBuilder()); - this->iceServer->GetSelectedTuple()->FillJson(data["iceSelectedTuple"]); + auto notification = FBS::WebRtcTransport::CreateIceSelectedTupleChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), tuple); - this->shared->channelNotifier->Emit(this->id, "iceselectedtuplechange", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_ICE_SELECTED_TUPLE_CHANGE, + FBS::Notification::Body::FBS_WebRtcTransport_IceSelectedTupleChangeNotification, + notification); } inline void WebRtcTransport::OnIceServerConnected(const RTC::IceServer* /*iceServer*/) @@ -1314,11 +1241,14 @@ namespace RTC MS_DEBUG_TAG(ice, "ICE connected"); // Notify the Node WebRtcTransport. - json data = json::object(); - - data["iceState"] = "connected"; + auto iceStateChangeOffset = FBS::WebRtcTransport::CreateIceStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::WebRtcTransport::IceState::CONNECTED); - this->shared->channelNotifier->Emit(this->id, "icestatechange", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_ICE_STATE_CHANGE, + FBS::Notification::Body::FBS_WebRtcTransport_IceStateChangeNotification, + iceStateChangeOffset); // If ready, run the DTLS handler. MayRunDtlsTransport(); @@ -1337,11 +1267,14 @@ namespace RTC MS_DEBUG_TAG(ice, "ICE completed"); // Notify the Node WebRtcTransport. - json data = json::object(); + auto iceStateChangeOffset = FBS::WebRtcTransport::CreateIceStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::WebRtcTransport::IceState::COMPLETED); - data["iceState"] = "completed"; - - this->shared->channelNotifier->Emit(this->id, "icestatechange", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_ICE_STATE_CHANGE, + FBS::Notification::Body::FBS_WebRtcTransport_IceStateChangeNotification, + iceStateChangeOffset); // If ready, run the DTLS handler. MayRunDtlsTransport(); @@ -1360,11 +1293,15 @@ namespace RTC MS_DEBUG_TAG(ice, "ICE disconnected"); // Notify the Node WebRtcTransport. - json data = json::object(); - - data["iceState"] = "disconnected"; + auto iceStateChangeOffset = FBS::WebRtcTransport::CreateIceStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::WebRtcTransport::IceState::DISCONNECTED); - this->shared->channelNotifier->Emit(this->id, "icestatechange", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_ICE_STATE_CHANGE, + FBS::Notification::Body::FBS_WebRtcTransport_IceStateChangeNotification, + iceStateChangeOffset); // If DTLS was already connected, notify the parent class. if (this->dtlsTransport->GetState() == RTC::DtlsTransport::DtlsState::CONNECTED) @@ -1380,11 +1317,14 @@ namespace RTC MS_DEBUG_TAG(dtls, "DTLS connecting"); // Notify the Node WebRtcTransport. - json data = json::object(); - - data["dtlsState"] = "connecting"; - - this->shared->channelNotifier->Emit(this->id, "dtlsstatechange", data); + auto dtlsStateChangeOffset = FBS::WebRtcTransport::CreateDtlsStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::WebRtcTransport::DtlsState::CONNECTING); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_DTLS_STATE_CHANGE, + FBS::Notification::Body::FBS_WebRtcTransport_DtlsStateChangeNotification, + dtlsStateChangeOffset); } inline void WebRtcTransport::OnDtlsTransportConnected( @@ -1423,12 +1363,16 @@ namespace RTC RTC::SrtpSession::Type::INBOUND, srtpCryptoSuite, srtpRemoteKey, srtpRemoteKeyLen); // Notify the Node WebRtcTransport. - json data = json::object(); - - data["dtlsState"] = "connected"; - data["dtlsRemoteCert"] = remoteCert; + auto dtlsStateChangeOffset = FBS::WebRtcTransport::CreateDtlsStateChangeNotificationDirect( + this->shared->channelNotifier->GetBufferBuilder(), + FBS::WebRtcTransport::DtlsState::CONNECTED, + remoteCert.c_str()); - this->shared->channelNotifier->Emit(this->id, "dtlsstatechange", data); + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_DTLS_STATE_CHANGE, + FBS::Notification::Body::FBS_WebRtcTransport_DtlsStateChangeNotification, + dtlsStateChangeOffset); // Tell the parent class. RTC::Transport::Connected(); @@ -1449,11 +1393,14 @@ namespace RTC MS_WARN_TAG(dtls, "DTLS failed"); // Notify the Node WebRtcTransport. - json data = json::object(); - - data["dtlsState"] = "failed"; - - this->shared->channelNotifier->Emit(this->id, "dtlsstatechange", data); + auto dtlsStateChangeOffset = FBS::WebRtcTransport::CreateDtlsStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::WebRtcTransport::DtlsState::FAILED); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_DTLS_STATE_CHANGE, + FBS::Notification::Body::FBS_WebRtcTransport_DtlsStateChangeNotification, + dtlsStateChangeOffset); } inline void WebRtcTransport::OnDtlsTransportClosed(const RTC::DtlsTransport* /*dtlsTransport*/) @@ -1463,11 +1410,14 @@ namespace RTC MS_WARN_TAG(dtls, "DTLS remotely closed"); // Notify the Node WebRtcTransport. - json data = json::object(); - - data["dtlsState"] = "closed"; - - this->shared->channelNotifier->Emit(this->id, "dtlsstatechange", data); + auto dtlsStateChangeOffset = FBS::WebRtcTransport::CreateDtlsStateChangeNotification( + this->shared->channelNotifier->GetBufferBuilder(), FBS::WebRtcTransport::DtlsState::CLOSED); + + this->shared->channelNotifier->Emit( + this->id, + FBS::Notification::Event::WEBRTCTRANSPORT_DTLS_STATE_CHANGE, + FBS::Notification::Body::FBS_WebRtcTransport_DtlsStateChangeNotification, + dtlsStateChangeOffset); // Tell the parent class. RTC::Transport::Disconnected(); diff --git a/worker/src/Settings.cpp b/worker/src/Settings.cpp index 786064d42d..c890b7361c 100644 --- a/worker/src/Settings.cpp +++ b/worker/src/Settings.cpp @@ -5,10 +5,10 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "Utils.hpp" -#include // isprint() +#include // isprint() +#include #include // std::ostream_iterator #include -#include #include // std::ostringstream #include extern "C" @@ -263,31 +263,28 @@ void Settings::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::WORKER_UPDATE_SETTINGS: + case Channel::ChannelRequest::Method::WORKER_UPDATE_SETTINGS: { - auto jsonLogLevelIt = request->data.find("logLevel"); - auto jsonLogTagsIt = request->data.find("logTags"); + auto body = request->data->body_as(); - // Update logLevel if requested. - if (jsonLogLevelIt != request->data.end() && jsonLogLevelIt->is_string()) + if (flatbuffers::IsFieldPresent(body, FBS::Worker::UpdateSettingsRequest::VT_LOGLEVEL)) { - std::string logLevel = *jsonLogLevelIt; + auto logLevel = body->logLevel()->str(); // This may throw. Settings::SetLogLevel(logLevel); } // Update logTags if requested. - if (jsonLogTagsIt != request->data.end() && jsonLogTagsIt->is_array()) + if (flatbuffers::IsFieldPresent(body, FBS::Worker::UpdateSettingsRequest::VT_LOGTAGS)) { std::vector logTags; - for (const auto& logTag : *jsonLogTagsIt) + for (const auto& logTag : *body->logTags()) { - if (logTag.is_string()) - logTags.push_back(logTag); + logTags.push_back(logTag->str()); } Settings::SetLogTags(logTags); @@ -303,7 +300,7 @@ void Settings::HandleRequest(Channel::ChannelRequest* request) default: { - MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + MS_THROW_ERROR("unknown method '%s'", request->methodCStr); } } } diff --git a/worker/src/Utils/String.cpp b/worker/src/Utils/String.cpp index 0e5cdd2ede..04086187cb 100644 --- a/worker/src/Utils/String.cpp +++ b/worker/src/Utils/String.cpp @@ -170,43 +170,4 @@ namespace Utils return Base64Decode(data, str.size(), outLen); } - - std::vector Utils::String::Split(const std::string& str, char separator, size_t limit) - { - std::vector items; - size_t pos = 0; - - while (pos < str.length()) - { - auto found = str.find(separator, pos); - - std::string item; - if (found != std::string::npos) - { - item = str.substr(pos, found - pos); - items.push_back(item); - } - else - { - item = str.substr(pos, str.size()); - items.push_back(item); - - break; - } - - // Escape the separator character. - pos += item.length() + 1; - - // Limit reached, add the remaining buffer to the last item. - if (limit != 0 && items.size() >= limit) - { - item = str.substr(pos, str.size()); - items.push_back(item); - - break; - } - } - - return items; - } } // namespace Utils diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index 9914efb9c2..18d31cb267 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -9,29 +9,25 @@ #include "MediaSoupErrors.hpp" #include "Settings.hpp" #include "Channel/ChannelNotifier.hpp" -#include "PayloadChannel/PayloadChannelNotifier.hpp" +#include "FBS/response_generated.h" +#include "FBS/worker_generated.h" /* Instance methods. */ -Worker::Worker(::Channel::ChannelSocket* channel, PayloadChannel::PayloadChannelSocket* payloadChannel) - : channel(channel), payloadChannel(payloadChannel) +Worker::Worker(::Channel::ChannelSocket* channel) : channel(channel) { MS_TRACE(); // Set us as Channel's listener. this->channel->SetListener(this); - // Set us as PayloadChannel's listener. - this->payloadChannel->SetListener(this); - // Set the SignalHandler. this->signalsHandler = new SignalsHandler(this); // Set up the RTC::Shared singleton. this->shared = new RTC::Shared( /*channelMessageRegistrator*/ new ChannelMessageRegistrator(), - /*channelNotifier*/ new Channel::ChannelNotifier(this->channel), - /*payloadChannelNotifier*/ new PayloadChannel::PayloadChannelNotifier(this->payloadChannel)); + /*channelNotifier*/ new Channel::ChannelNotifier(this->channel)); #ifdef MS_EXECUTABLE { @@ -45,7 +41,8 @@ Worker::Worker(::Channel::ChannelSocket* channel, PayloadChannel::PayloadChannel DepUsrSCTP::CreateChecker(); // Tell the Node process that we are running. - this->shared->channelNotifier->Emit(Logger::pid, "running"); + this->shared->channelNotifier->Emit( + std::to_string(Logger::pid), FBS::Notification::Event::WORKER_RUNNING); MS_DEBUG_DEV("starting libuv loop"); DepLibUV::RunLoop(); @@ -98,48 +95,41 @@ void Worker::Close() // Close the Channel. this->channel->Close(); - - // Close the PayloadChannel. - this->payloadChannel->Close(); } -void Worker::FillJson(json& jsonObject) const +flatbuffers::Offset Worker::FillBuffer( + flatbuffers::FlatBufferBuilder& builder) const { - MS_TRACE(); - - // Add pid. - jsonObject["pid"] = Logger::pid; - // Add webRtcServerIds. - jsonObject["webRtcServerIds"] = json::array(); - auto jsonWebRtcServerIdsIt = jsonObject.find("webRtcServerIds"); + std::vector> webRtcServerIds; + webRtcServerIds.reserve(this->mapWebRtcServers.size()); for (const auto& kv : this->mapWebRtcServers) { const auto& webRtcServerId = kv.first; - jsonWebRtcServerIdsIt->emplace_back(webRtcServerId); + webRtcServerIds.push_back(builder.CreateString(webRtcServerId)); } // Add routerIds. - jsonObject["routerIds"] = json::array(); - auto jsonRouterIdsIt = jsonObject.find("routerIds"); + std::vector> routerIds; + routerIds.reserve(this->mapRouters.size()); for (const auto& kv : this->mapRouters) { const auto& routerId = kv.first; - jsonRouterIdsIt->emplace_back(routerId); + routerIds.push_back(builder.CreateString(routerId)); } - // Add channelMessageHandlers. - jsonObject["channelMessageHandlers"] = json::object(); - auto jsonChannelMessageHandlersIt = jsonObject.find("channelMessageHandlers"); + auto channelMessageHandlers = this->shared->channelMessageRegistrator->FillBuffer(builder); - this->shared->channelMessageRegistrator->FillJson(*jsonChannelMessageHandlersIt); + return FBS::Worker::CreateDumpResponseDirect( + builder, Logger::pid, &webRtcServerIds, &routerIds, channelMessageHandlers); } -void Worker::FillJsonResourceUsage(json& jsonObject) const +flatbuffers::Offset Worker::FillBufferResourceUsage( + flatbuffers::FlatBufferBuilder& builder) const { MS_TRACE(); @@ -151,123 +141,85 @@ void Worker::FillJsonResourceUsage(json& jsonObject) const if (err != 0) MS_THROW_ERROR("uv_getrusagerequest() failed: %s", uv_strerror(err)); - // Add ru_utime (uv_timeval_t, user CPU time used, converted to ms). - jsonObject["ru_utime"] = - (uvRusage.ru_utime.tv_sec * static_cast(1000)) + (uvRusage.ru_utime.tv_usec / 1000); - - // Add ru_stime (uv_timeval_t, system CPU time used, converted to ms). - jsonObject["ru_stime"] = - (uvRusage.ru_stime.tv_sec * static_cast(1000)) + (uvRusage.ru_stime.tv_usec / 1000); + return FBS::Worker::CreateResourceUsageResponse( + builder, + // Add ru_utime (uv_timeval_t, user CPU time used, converted to ms). + (uvRusage.ru_utime.tv_sec * static_cast(1000)) + (uvRusage.ru_utime.tv_usec / 1000), + // Add ru_stime (uv_timeval_t, system CPU time used, converted to ms). + (uvRusage.ru_stime.tv_sec * static_cast(1000)) + (uvRusage.ru_stime.tv_usec / 1000), + // Add ru_maxrss (uint64_t, maximum resident set size). + uvRusage.ru_maxrss, - // Add ru_maxrss (uint64_t, maximum resident set size). - jsonObject["ru_maxrss"] = uvRusage.ru_maxrss; + // Add ru_ixrss (uint64_t, integral shared memory size). + uvRusage.ru_ixrss, - // Add ru_ixrss (uint64_t, integral shared memory size). - jsonObject["ru_ixrss"] = uvRusage.ru_ixrss; + // Add ru_idrss (uint64_t, integral unshared data size). + uvRusage.ru_idrss, - // Add ru_idrss (uint64_t, integral unshared data size). - jsonObject["ru_idrss"] = uvRusage.ru_idrss; + // Add ru_isrss (uint64_t, integral unshared stack size). + uvRusage.ru_isrss, - // Add ru_isrss (uint64_t, integral unshared stack size). - jsonObject["ru_isrss"] = uvRusage.ru_isrss; + // Add ru_minflt (uint64_t, page reclaims, soft page faults). + uvRusage.ru_minflt, - // Add ru_minflt (uint64_t, page reclaims, soft page faults). - jsonObject["ru_minflt"] = uvRusage.ru_minflt; + // Add ru_majflt (uint64_t, page faults, hard page faults). + uvRusage.ru_majflt, - // Add ru_majflt (uint64_t, page faults, hard page faults). - jsonObject["ru_majflt"] = uvRusage.ru_majflt; + // Add ru_nswap (uint64_t, swaps). + uvRusage.ru_nswap, - // Add ru_nswap (uint64_t, swaps). - jsonObject["ru_nswap"] = uvRusage.ru_nswap; + // Add ru_inblock (uint64_t, block input operations). + uvRusage.ru_inblock, - // Add ru_inblock (uint64_t, block input operations). - jsonObject["ru_inblock"] = uvRusage.ru_inblock; + // Add ru_oublock (uint64_t, block output operations). + uvRusage.ru_oublock, - // Add ru_oublock (uint64_t, block output operations). - jsonObject["ru_oublock"] = uvRusage.ru_oublock; + // Add ru_msgsnd (uint64_t, IPC messages sent). + uvRusage.ru_msgsnd, - // Add ru_msgsnd (uint64_t, IPC messages sent). - jsonObject["ru_msgsnd"] = uvRusage.ru_msgsnd; + // Add ru_msgrcv (uint64_t, IPC messages received). + uvRusage.ru_msgrcv, - // Add ru_msgrcv (uint64_t, IPC messages received). - jsonObject["ru_msgrcv"] = uvRusage.ru_msgrcv; - - // Add ru_nsignals (uint64_t, signals received). - jsonObject["ru_nsignals"] = uvRusage.ru_nsignals; - - // Add ru_nvcsw (uint64_t, voluntary context switches). - jsonObject["ru_nvcsw"] = uvRusage.ru_nvcsw; - - // Add ru_nivcsw (uint64_t, involuntary context switches). - jsonObject["ru_nivcsw"] = uvRusage.ru_nivcsw; + // Add ru_nsignals (uint64_t, signals received). + uvRusage.ru_nsignals, + // Add ru_nvcsw (uint64_t, voluntary context switches). + uvRusage.ru_nvcsw, + // Add ru_nivcsw (uint64_t, involuntary context switches). + uvRusage.ru_nivcsw); } -void Worker::SetNewWebRtcServerIdFromData(json& data, std::string& webRtcServerId) const +RTC::Router* Worker::GetRouter(const std::string& routerId) const { MS_TRACE(); - auto jsonWebRtcServerIdIt = data.find("webRtcServerId"); + auto it = this->mapRouters.find(routerId); - if (jsonWebRtcServerIdIt == data.end() || !jsonWebRtcServerIdIt->is_string()) - MS_THROW_ERROR("missing webRtcServerId"); - - webRtcServerId.assign(jsonWebRtcServerIdIt->get()); + if (it == this->mapRouters.end()) + MS_THROW_ERROR("Router not found"); - if (this->mapWebRtcServers.find(webRtcServerId) != this->mapWebRtcServers.end()) - MS_THROW_ERROR("a WebRtcServer with same webRtcServerId already exists"); + return it->second; } -RTC::WebRtcServer* Worker::GetWebRtcServerFromData(json& data) const +void Worker::CheckNoWebRtcServer(const std::string& webRtcServerId) const { - MS_TRACE(); - - auto jsonWebRtcServerIdIt = data.find("webRtcServerId"); - - if (jsonWebRtcServerIdIt == data.end() || !jsonWebRtcServerIdIt->is_string()) - MS_THROW_ERROR("missing handlerId.webRtcServerId"); - - auto it = this->mapWebRtcServers.find(jsonWebRtcServerIdIt->get()); - - if (it == this->mapWebRtcServers.end()) - MS_THROW_ERROR("WebRtcServer not found"); - - RTC::WebRtcServer* webRtcServer = it->second; - - return webRtcServer; + if (this->mapWebRtcServers.find(webRtcServerId) != this->mapWebRtcServers.end()) + MS_THROW_ERROR("a WebRtcServer with same webRtcServerId already exists"); } -void Worker::SetNewRouterIdFromData(json& data, std::string& routerId) const +void Worker::CheckNoRouter(const std::string& routerId) const { - MS_TRACE(); - - auto jsonRouterIdIt = data.find("routerId"); - - if (jsonRouterIdIt == data.end() || !jsonRouterIdIt->is_string()) - MS_THROW_ERROR("missing routerId"); - - routerId.assign(jsonRouterIdIt->get()); - if (this->mapRouters.find(routerId) != this->mapRouters.end()) MS_THROW_ERROR("a Router with same routerId already exists"); } -RTC::Router* Worker::GetRouterFromData(json& data) const +RTC::WebRtcServer* Worker::GetWebRtcServer(const std::string& webRtcServerId) const { - MS_TRACE(); - - auto jsonRouterIdIt = data.find("routerId"); - - if (jsonRouterIdIt == data.end() || !jsonRouterIdIt->is_string()) - MS_THROW_ERROR("missing routerId"); - - auto it = this->mapRouters.find(jsonRouterIdIt->get()); - - if (it == this->mapRouters.end()) - MS_THROW_ERROR("Router not found"); + auto it = this->mapWebRtcServers.find(webRtcServerId); - RTC::Router* router = it->second; + if (it == this->mapWebRtcServers.end()) + MS_THROW_ERROR("WebRtcServer not found"); - return router; + return it->second; } inline void Worker::HandleRequest(Channel::ChannelRequest* request) @@ -275,11 +227,11 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) MS_TRACE(); MS_DEBUG_DEV( - "Channel request received [method:%s, id:%" PRIu32 "]", request->method.c_str(), request->id); + "Channel request received [method:%s, id:%" PRIu32 "]", request->methodCStr, request->id); - switch (request->methodId) + switch (request->method) { - case Channel::ChannelRequest::MethodId::WORKER_CLOSE: + case Channel::ChannelRequest::Method::WORKER_CLOSE: { if (this->closed) return; @@ -291,44 +243,42 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) break; } - case Channel::ChannelRequest::MethodId::WORKER_DUMP: + case Channel::ChannelRequest::Method::WORKER_DUMP: { - json data = json::object(); - - FillJson(data); + auto dumpOffset = FillBuffer(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_Worker_DumpResponse, dumpOffset); break; } - case Channel::ChannelRequest::MethodId::WORKER_GET_RESOURCE_USAGE: + case Channel::ChannelRequest::Method::WORKER_GET_RESOURCE_USAGE: { - json data = json::object(); - - FillJsonResourceUsage(data); + auto resourceUsageOffset = FillBufferResourceUsage(request->GetBufferBuilder()); - request->Accept(data); + request->Accept(FBS::Response::Body::FBS_Worker_ResourceUsageResponse, resourceUsageOffset); break; } - case Channel::ChannelRequest::MethodId::WORKER_UPDATE_SETTINGS: + case Channel::ChannelRequest::Method::WORKER_UPDATE_SETTINGS: { Settings::HandleRequest(request); break; } - case Channel::ChannelRequest::MethodId::WORKER_CREATE_WEBRTC_SERVER: + case Channel::ChannelRequest::Method::WORKER_CREATE_WEBRTC_SERVER: { try { - std::string webRtcServerId; + auto body = request->data->body_as(); - SetNewWebRtcServerIdFromData(request->data, webRtcServerId); + std::string webRtcServerId = body->webRtcServerId()->str(); - auto* webRtcServer = new RTC::WebRtcServer(this->shared, webRtcServerId, request->data); + CheckNoWebRtcServer(webRtcServerId); + + auto* webRtcServer = new RTC::WebRtcServer(this->shared, webRtcServerId, body->listenInfos()); this->mapWebRtcServers[webRtcServerId] = webRtcServer; @@ -338,27 +288,31 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) } catch (const MediaSoupTypeError& error) { - MS_THROW_TYPE_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + MS_THROW_TYPE_ERROR("%s [method:%s]", error.what(), request->methodCStr); } catch (const MediaSoupError& error) { - MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + MS_THROW_ERROR("%s [method:%s]", error.what(), request->methodCStr); } break; } - case Channel::ChannelRequest::MethodId::WORKER_WEBRTC_SERVER_CLOSE: + case Channel::ChannelRequest::Method::WORKER_WEBRTC_SERVER_CLOSE: { RTC::WebRtcServer* webRtcServer{ nullptr }; + auto body = request->data->body_as(); + + auto webRtcServerId = body->webRtcServerId()->str(); + try { - webRtcServer = GetWebRtcServerFromData(request->data); + webRtcServer = GetWebRtcServer(webRtcServerId); } catch (const MediaSoupError& error) { - MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + MS_THROW_ERROR("%s [method:%s]", error.what(), request->methodCStr); } // Remove it from the map and delete it. @@ -373,17 +327,19 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) break; } - case Channel::ChannelRequest::MethodId::WORKER_CREATE_ROUTER: + case Channel::ChannelRequest::Method::WORKER_CREATE_ROUTER: { - std::string routerId; + auto body = request->data->body_as(); + + auto routerId = body->routerId()->str(); try { - SetNewRouterIdFromData(request->data, routerId); + CheckNoRouter(routerId); } catch (const MediaSoupError& error) { - MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + MS_THROW_ERROR("%s [method:%s]", error.what(), request->methodCStr); } auto* router = new RTC::Router(this->shared, routerId, this); @@ -397,17 +353,21 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) break; } - case Channel::ChannelRequest::MethodId::WORKER_CLOSE_ROUTER: + case Channel::ChannelRequest::Method::WORKER_CLOSE_ROUTER: { RTC::Router* router{ nullptr }; + auto body = request->data->body_as(); + + auto routerId = body->routerId()->str(); + try { - router = GetRouterFromData(request->data); + router = GetRouter(routerId); } catch (const MediaSoupError& error) { - MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + MS_THROW_ERROR("%s [method:%s]", error.what(), request->methodCStr); } // Remove it from the map and delete it. @@ -439,11 +399,11 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) } catch (const MediaSoupTypeError& error) { - MS_THROW_TYPE_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + MS_THROW_TYPE_ERROR("%s [method:%s]", error.what(), request->methodCStr); } catch (const MediaSoupError& error) { - MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + MS_THROW_ERROR("%s [method:%s]", error.what(), request->methodCStr); } break; @@ -451,90 +411,44 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) } } -inline void Worker::OnChannelClosed(Channel::ChannelSocket* /*socket*/) -{ - MS_TRACE_STD(); - - // Only needed for executable, library user can close channel earlier and it is fine. -#ifdef MS_EXECUTABLE - // If the pipe is remotely closed it may mean that mediasoup Node process - // abruptly died (SIGKILL?) so we must die. - MS_ERROR_STD("channel remotely closed, closing myself"); -#endif - - Close(); -} - -inline void Worker::HandleRequest(PayloadChannel::PayloadChannelRequest* request) +inline void Worker::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); - MS_DEBUG_DEV( - "PayloadChannel request received [method:%s, id:%" PRIu32 "]", - request->method.c_str(), - request->id); + MS_DEBUG_DEV("Channel notification received [event:%s]", notification->eventCStr); try { auto* handler = - this->shared->channelMessageRegistrator->GetPayloadChannelRequestHandler(request->handlerId); - - if (handler == nullptr) - { - MS_THROW_ERROR( - "PayloadChannel request handler with ID %s not found", request->handlerId.c_str()); - } - - handler->HandleRequest(request); - } - catch (const MediaSoupTypeError& error) - { - MS_THROW_TYPE_ERROR("%s [method:%s]", error.what(), request->method.c_str()); - } - catch (const MediaSoupError& error) - { - MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); - } -} - -inline void Worker::HandleNotification(PayloadChannel::PayloadChannelNotification* notification) -{ - MS_TRACE(); - - MS_DEBUG_DEV("PayloadChannel notification received [event:%s]", notification->event.c_str()); - - try - { - auto* handler = this->shared->channelMessageRegistrator->GetPayloadChannelNotificationHandler( - notification->handlerId); + this->shared->channelMessageRegistrator->GetChannelNotificationHandler(notification->handlerId); if (handler == nullptr) { MS_THROW_ERROR( - "PayloadChannel notification handler with ID %s not found", notification->handlerId.c_str()); + "Channel notification handler with ID %s not found", notification->handlerId.c_str()); } handler->HandleNotification(notification); } catch (const MediaSoupTypeError& error) { - MS_THROW_TYPE_ERROR("%s [event:%s]", error.what(), notification->event.c_str()); + MS_THROW_TYPE_ERROR("%s [event:%s]", error.what(), notification->eventCStr); } catch (const MediaSoupError& error) { - MS_THROW_ERROR("%s [method:%s]", error.what(), notification->event.c_str()); + MS_THROW_ERROR("%s [method:%s]", error.what(), notification->eventCStr); } } -inline void Worker::OnPayloadChannelClosed(PayloadChannel::PayloadChannelSocket* /*payloadChannel*/) +inline void Worker::OnChannelClosed(Channel::ChannelSocket* /*socket*/) { - MS_TRACE(); + MS_TRACE_STD(); // Only needed for executable, library user can close channel earlier and it is fine. #ifdef MS_EXECUTABLE // If the pipe is remotely closed it may mean that mediasoup Node process // abruptly died (SIGKILL?) so we must die. - MS_ERROR_STD("payloadChannel remotely closed, closing myself"); + MS_ERROR_STD("channel remotely closed, closing myself"); #endif Close(); diff --git a/worker/src/lib.cpp b/worker/src/lib.cpp index 86246cf270..54e3ca9cb5 100644 --- a/worker/src/lib.cpp +++ b/worker/src/lib.cpp @@ -13,7 +13,6 @@ #include "Utils.hpp" #include "Worker.hpp" #include "Channel/ChannelSocket.hpp" -#include "PayloadChannel/PayloadChannelSocket.hpp" #include "RTC/DtlsTransport.hpp" #include "RTC/SrtpSession.hpp" #include @@ -37,11 +36,7 @@ extern "C" int mediasoup_worker_run( ChannelReadFn channelReadFn, ChannelReadCtx channelReadCtx, ChannelWriteFn channelWriteFn, - ChannelWriteCtx channelWriteCtx, - PayloadChannelReadFn payloadChannelReadFn, - PayloadChannelReadCtx payloadChannelReadCtx, - PayloadChannelWriteFn payloadChannelWriteFn, - PayloadChannelWriteCtx payloadChannelWriteCtx) + ChannelWriteCtx channelWriteCtx) { // Initialize libuv stuff (we need it for the Channel). DepLibUV::ClassInit(); @@ -51,11 +46,6 @@ extern "C" int mediasoup_worker_run( // deallocate its UV handles. std::unique_ptr channel{ nullptr }; - // PayloadChannel socket. If Worker instance runs properly, this socket is - // closed by it in its destructor. Otherwise it's closed here by also letting - // libuv deallocate its UV handles. - std::unique_ptr payloadChannel{ nullptr }; - try { if (channelReadFn) @@ -78,30 +68,6 @@ extern "C" int mediasoup_worker_run( return 1; } - try - { - if (payloadChannelReadFn) - { - payloadChannel.reset(new PayloadChannel::PayloadChannelSocket( - payloadChannelReadFn, payloadChannelReadCtx, payloadChannelWriteFn, payloadChannelWriteCtx)); - } - else - { - payloadChannel.reset( - new PayloadChannel::PayloadChannelSocket(payloadConsumeChannelFd, payloadProduceChannelFd)); - } - } - catch (const MediaSoupError& error) - { - MS_ERROR_STD("error creating the PayloadChannel: %s", error.what()); - - channel->Close(); - DepLibUV::RunLoop(); - DepLibUV::ClassDestroy(); - - return 1; - } - // Initialize the Logger. Logger::ClassInit(channel.get()); @@ -114,7 +80,6 @@ extern "C" int mediasoup_worker_run( MS_ERROR_STD("settings error: %s", error.what()); channel->Close(); - payloadChannel->Close(); DepLibUV::RunLoop(); DepLibUV::ClassDestroy(); @@ -126,7 +91,6 @@ extern "C" int mediasoup_worker_run( MS_ERROR_STD("unexpected settings error: %s", error.what()); channel->Close(); - payloadChannel->Close(); DepLibUV::RunLoop(); DepLibUV::ClassDestroy(); @@ -171,7 +135,7 @@ extern "C" int mediasoup_worker_run( #endif // Run the Worker. - Worker worker(channel.get(), payloadChannel.get()); + Worker worker(channel.get()); // Free static stuff. DepLibSRTP::ClassDestroy(); diff --git a/worker/src/lib.rs b/worker/src/lib.rs index 0e4f4e4fb7..fe8aae3d16 100644 --- a/worker/src/lib.rs +++ b/worker/src/lib.rs @@ -38,43 +38,6 @@ pub type ChannelWriteFn = unsafe extern "C" fn( unsafe impl Send for ChannelWriteCtx {} -#[repr(transparent)] -pub struct PayloadChannelReadCtx(pub *const c_void); -pub type PayloadChannelReadFreeFn = Option< - unsafe extern "C" fn( - /* message: */ *mut u8, - /* message_len: */ u32, - /* message_ctx: */ usize, - ), ->; -pub type PayloadChannelReadFn = unsafe extern "C" fn( - /* message: */ *mut *mut u8, - /* message_len: */ *mut u32, - /* message_ctx: */ *mut usize, - /* payload: */ *mut *mut u8, - /* payload_len: */ *mut u32, - /* payload_capacity: */ *mut usize, - // This is `uv_async_t` handle that can be called later with `uv_async_send()` when there is - // more data to read - /* handle */ - UvAsyncT, - /* ctx: */ PayloadChannelReadCtx, -) -> PayloadChannelReadFreeFn; - -unsafe impl Send for PayloadChannelReadCtx {} - -#[repr(transparent)] -pub struct PayloadChannelWriteCtx(pub *const c_void); -pub type PayloadChannelWriteFn = unsafe extern "C" fn( - /* message: */ *const u8, - /* message_len: */ u32, - /* payload: */ *const u8, - /* payload_len: */ u32, - /* ctx: */ PayloadChannelWriteCtx, -); - -unsafe impl Send for PayloadChannelWriteCtx {} - #[link(name = "mediasoup-worker", kind = "static")] extern "C" { /// Returns `0` on success, or an error code `< 0` on failure @@ -92,9 +55,5 @@ extern "C" { channel_read_ctx: ChannelReadCtx, channel_write_fn: ChannelWriteFn, channel_write_ctx: ChannelWriteCtx, - payload_channel_read_fn: PayloadChannelReadFn, - payload_channel_read_ctx: PayloadChannelReadCtx, - payload_channel_write_fn: PayloadChannelWriteFn, - payload_channel_write_ctx: PayloadChannelWriteCtx, ) -> c_int; } diff --git a/worker/src/main.cpp b/worker/src/main.cpp index fcf4f47872..f53b8257a7 100644 --- a/worker/src/main.cpp +++ b/worker/src/main.cpp @@ -34,10 +34,6 @@ int main(int argc, char* argv[]) nullptr, nullptr, nullptr, - nullptr, - nullptr, - nullptr, - nullptr, nullptr); switch (statusCode) diff --git a/worker/subprojects/flatbuffers.wrap b/worker/subprojects/flatbuffers.wrap new file mode 100644 index 0000000000..630611bdb1 --- /dev/null +++ b/worker/subprojects/flatbuffers.wrap @@ -0,0 +1,14 @@ +[wrap-file] +directory = flatbuffers-23.3.3 +source_url = https://github.com/google/flatbuffers/archive/v23.3.3.tar.gz +source_filename = flatbuffers-23.3.3.tar.gz +source_hash = 8aff985da30aaab37edf8e5b02fda33ed4cbdd962699a8e2af98fdef306f4e4d +patch_filename = flatbuffers_23.3.3-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/flatbuffers_23.3.3-1/get_patch +patch_hash = fa5faa75a99d1161be532a5d5db19543c15cb193d116d24827a251fc03488a14 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/flatbuffers_23.3.3-1/flatbuffers-23.3.3.tar.gz +wrapdb_version = 23.3.3-1 + +[provide] +flatbuffers = flatbuffers_dep +program_names = flatc, flathash diff --git a/worker/subprojects/nlohmann_json.wrap b/worker/subprojects/nlohmann_json.wrap deleted file mode 100644 index 857277a676..0000000000 --- a/worker/subprojects/nlohmann_json.wrap +++ /dev/null @@ -1,10 +0,0 @@ -[wrap-file] -directory = nlohmann_json-3.10.5 -lead_directory_missing = true -source_url = https://github.com/nlohmann/json/releases/download/v3.10.5/include.zip -source_filename = nlohmann_json-3.10.5.zip -source_hash = b94997df68856753b72f0d7a3703b7d484d4745c567f3584ef97c96c25a5798e - -[provide] -nlohmann_json = nlohmann_json_dep - diff --git a/worker/test/src/RTC/TestRtpPacketH264Svc.cpp b/worker/test/src/RTC/TestRtpPacketH264Svc.cpp index 022bee4a13..970cc73284 100644 --- a/worker/test/src/RTC/TestRtpPacketH264Svc.cpp +++ b/worker/test/src/RTC/TestRtpPacketH264Svc.cpp @@ -4,6 +4,7 @@ #include "RTC/RtpPacket.hpp" #include #include // std::memset() +#include #include #include diff --git a/worker/test/src/Utils/TestJson.cpp b/worker/test/src/Utils/TestJson.cpp deleted file mode 100644 index 03ab8800e1..0000000000 --- a/worker/test/src/Utils/TestJson.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include "common.hpp" -#include "Utils.hpp" -#include -#include - -using namespace Utils; -using json = nlohmann::json; - -SCENARIO("Json::IsPositiveInteger()") -{ - json jsonValue; - int intValue; - int8_t int8Value; - int32_t int32Value; - unsigned int uintValue; - uint8_t uint8Value; - uint32_t uint32Value; - float floatValue; - json jsonArray{ json::array() }; - json jsonObject{ json::object() }; - - jsonValue = 0; - REQUIRE(Json::IsPositiveInteger(jsonValue)); - - jsonValue = 1; - REQUIRE(Json::IsPositiveInteger(jsonValue)); - - jsonValue = 0u; - REQUIRE(Json::IsPositiveInteger(jsonValue)); - - jsonValue = 1u; - REQUIRE(Json::IsPositiveInteger(jsonValue)); - - jsonValue = -1; - REQUIRE(!Json::IsPositiveInteger(jsonValue)); - - intValue = 0; - REQUIRE(Json::IsPositiveInteger(intValue)); - - intValue = 1; - REQUIRE(Json::IsPositiveInteger(intValue)); - - intValue = -1; - REQUIRE(!Json::IsPositiveInteger(intValue)); - - int8Value = 0; - REQUIRE(Json::IsPositiveInteger(int8Value)); - - int8Value = 1; - REQUIRE(Json::IsPositiveInteger(int8Value)); - - int8Value = -1; - REQUIRE(!Json::IsPositiveInteger(int8Value)); - - int32Value = 0; - REQUIRE(Json::IsPositiveInteger(int32Value)); - - int32Value = 1; - REQUIRE(Json::IsPositiveInteger(int32Value)); - - int32Value = -1; - REQUIRE(!Json::IsPositiveInteger(int32Value)); - - uintValue = 0; - REQUIRE(Json::IsPositiveInteger(uintValue)); - - uintValue = 1; - REQUIRE(Json::IsPositiveInteger(uintValue)); - - uint8Value = 0; - REQUIRE(Json::IsPositiveInteger(uint8Value)); - - uint8Value = 1; - REQUIRE(Json::IsPositiveInteger(uint8Value)); - - uint32Value = 0; - REQUIRE(Json::IsPositiveInteger(uint32Value)); - - uint32Value = 1; - REQUIRE(Json::IsPositiveInteger(uint32Value)); - - floatValue = 0; - REQUIRE(!Json::IsPositiveInteger(floatValue)); - - floatValue = 0.0; - REQUIRE(!Json::IsPositiveInteger(floatValue)); - - floatValue = 1; - REQUIRE(!Json::IsPositiveInteger(floatValue)); - - floatValue = 1.1; - REQUIRE(!Json::IsPositiveInteger(floatValue)); - - floatValue = -1; - REQUIRE(!Json::IsPositiveInteger(floatValue)); - - floatValue = -1.1; - REQUIRE(!Json::IsPositiveInteger(floatValue)); - - REQUIRE(!Json::IsPositiveInteger(jsonArray)); - REQUIRE(!Json::IsPositiveInteger(jsonObject)); - REQUIRE(!Json::IsPositiveInteger(nullptr)); - REQUIRE(!Json::IsPositiveInteger(true)); - REQUIRE(!Json::IsPositiveInteger(false)); -} diff --git a/worker/test/src/Utils/TestString.cpp b/worker/test/src/Utils/TestString.cpp index 3b4dcf016d..99fe49e751 100644 --- a/worker/test/src/Utils/TestString.cpp +++ b/worker/test/src/Utils/TestString.cpp @@ -76,40 +76,3 @@ SCENARIO("String::Base64Encode() and String::Base64Decode()") REQUIRE(outLen == sizeof(rtpPacket)); REQUIRE(std::memcmp(decodedPtr, rtpPacket, outLen) == 0); } - -SCENARIO("String::Split()", "[utils][string]") -{ - SECTION("empty string") - { - std::string foo{}; - - auto v = String::Split(foo, ','); - - REQUIRE(v.size() == 0); - } - - SECTION("character separated string with no limit") - { - std::string foo{ "a,b,c,d" }; - - auto v = String::Split(foo, ','); - - REQUIRE(v.size() == 4); - REQUIRE(v[0] == "a"); - REQUIRE(v[1] == "b"); - REQUIRE(v[2] == "c"); - REQUIRE(v[3] == "d"); - } - - SECTION("character separated string with limit") - { - std::string foo{ "a,b,c,d" }; - - auto v = String::Split(foo, ',', 2); - - REQUIRE(v.size() == 3); - REQUIRE(v[0] == "a"); - REQUIRE(v[1] == "b"); - REQUIRE(v[2] == "c,d"); - } -}