/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set sw=2 ts=8 et tw=80 : */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsString.h" #include "nsTArray.h" #include "Capsule.h" #include "CapsuleEncoder.h" namespace mozilla::net { CapsuleEncoder::CapsuleEncoder() { NeqoEncoder::Init(getter_AddRefs(mEncoder)); MOZ_ASSERT(mEncoder); } CapsuleEncoder::~CapsuleEncoder() = default; void CapsuleEncoder::EncodeCapsule(Capsule& aCapsule) { if (aCapsule.mCapsule.is()) { auto& value = aCapsule.mCapsule.as(); EncodeVarint(value.mType).EncodeBufferWithVarintLen(value.mData); return; } if (aCapsule.mCapsule.is()) { const auto& value = aCapsule.mCapsule.as(); EncodeVarint(value.Type()) .EncodeVarint(4 + value.mReason.Length()) .EncodeUint(4, value.mStatus) .EncodeString(value.mReason); return; } if (aCapsule.mCapsule.is()) { auto& value = aCapsule.mCapsule.as(); EncodeVarint(value.Type()) .EncodeVarint(CapsuleEncoder::VarintLength(value.mMaxDataSize)) .EncodeVarint(value.mMaxDataSize); return; } if (aCapsule.mCapsule.is()) { auto& value = aCapsule.mCapsule.as(); uint64_t length = CapsuleEncoder::VarintLength(value.mID) + value.mData.Length(); EncodeVarint(value.Type()) .EncodeVarint(length) .EncodeVarint(value.mID) .EncodeBuffer(value.mData); mStreamMetadata = Some(StreamMetadata{ value.mID, value.mData.Length(), CapsuleEncoder::VarintLength(static_cast(value.Type())) + CapsuleEncoder::VarintLength(length) + CapsuleEncoder::VarintLength(value.mID)}); return; } if (aCapsule.mCapsule.is()) { auto& value = aCapsule.mCapsule.as(); EncodeVarint(value.Type()) .EncodeVarint(CapsuleEncoder::VarintLength(value.mLimit)) .EncodeVarint(value.mLimit); return; } if (aCapsule.mCapsule.is()) { auto& value = aCapsule.mCapsule.as(); EncodeVarint(value.Type()) .EncodeVarint(CapsuleEncoder::VarintLength(value.mLimit)) .EncodeVarint(value.mLimit); return; } if (aCapsule.mCapsule.is()) { auto& value = aCapsule.mCapsule.as(); EncodeVarint(value.Type()) .EncodeVarint(CapsuleEncoder::VarintLength(value.mID) + CapsuleEncoder::VarintLength(value.mLimit)) .EncodeVarint(value.mID) .EncodeVarint(value.mLimit); return; } if (aCapsule.mCapsule.is()) { auto& value = aCapsule.mCapsule.as(); EncodeVarint(value.Type()) .EncodeVarint(CapsuleEncoder::VarintLength(value.mID) + CapsuleEncoder::VarintLength(value.mLimit)) .EncodeVarint(value.mID) .EncodeVarint(value.mLimit); return; } if (aCapsule.mCapsule.is()) { auto& value = aCapsule.mCapsule.as(); EncodeVarint(value.Type()) .EncodeVarint(CapsuleEncoder::VarintLength(value.mLimit)) .EncodeVarint(value.mLimit); return; } if (aCapsule.mCapsule.is()) { auto& value = aCapsule.mCapsule.as(); EncodeVarint(value.Type()) .EncodeVarint(CapsuleEncoder::VarintLength(value.mID) + CapsuleEncoder::VarintLength(value.mErrorCode)) .EncodeVarint(value.mID) .EncodeVarint(value.mErrorCode); return; } if (aCapsule.mCapsule.is()) { auto& value = aCapsule.mCapsule.as(); EncodeVarint(value.Type()) .EncodeVarint(CapsuleEncoder::VarintLength(value.mID) + CapsuleEncoder::VarintLength(value.mErrorCode) + CapsuleEncoder::VarintLength(value.mReliableSize)) .EncodeVarint(value.mID) .EncodeVarint(value.mErrorCode) .EncodeVarint(value.mReliableSize); return; } if (aCapsule.mCapsule.is()) { auto& value = aCapsule.mCapsule.as(); uint64_t length = value.mPayload.Length(); EncodeVarint(value.Type()) .EncodeVarint(length) .EncodeBuffer(value.mPayload); return; } } CapsuleEncoder& CapsuleEncoder::EncodeByte(uint8_t aData) { mEncoder->EncodeByte(aData); return *this; } template CapsuleEncoder& CapsuleEncoder::EncodeUint(uint32_t aSize, T aValue) { uint64_t value = static_cast(aValue); mEncoder->EncodeUint(aSize, value); return *this; } template CapsuleEncoder& CapsuleEncoder::EncodeVarint(T aValue) { uint64_t value = static_cast(aValue); mEncoder->EncodeVarint(value); return *this; } CapsuleEncoder& CapsuleEncoder::EncodeString(const nsACString& aData) { mEncoder->EncodeBuffer(reinterpret_cast(aData.BeginReading()), aData.Length()); return *this; } CapsuleEncoder& CapsuleEncoder::EncodeBuffer(nsTArray& aData) { mEncoder->EncodeBuffer(aData.Elements(), aData.Length()); return *this; } CapsuleEncoder& CapsuleEncoder::EncodeBufferWithVarintLen( nsTArray& aData) { mEncoder->EncodeBufferWithVarintLen(aData.Elements(), aData.Length()); return *this; } // static size_t CapsuleEncoder::VarintLength(uint64_t aValue) { return NeqoEncoder::VarintLength(aValue); } mozilla::Span CapsuleEncoder::GetBuffer() { const uint8_t* buffer = nullptr; uint32_t length = 0; mEncoder->GetData(&buffer, &length); return Span(buffer, length); } } // namespace mozilla::net