blob: bf117410cdf9d199f359f1065b8fea38545bddea [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <wlan/common/element.h>
#include <wlan/common/from_bytes.h>
#include <wlan/common/element_splitter.h>
namespace wlan {
namespace common {
static void SkipIfTooShort(Span<const uint8_t>* span) {
const ElementHeader* header = FromBytes<ElementHeader>(*span);
if (header == nullptr || header->len + sizeof(ElementHeader) > span->size()) {
// If there is not enough remaining bytes to hold the full element,
// move the iterator to the end
*span = Span { span->data() + span->size(), static_cast<size_t>(0u) };
}
}
ElementIterator::ElementIterator(Span<const uint8_t> buffer) : remaining_(buffer) {
SkipIfTooShort(&remaining_);
}
std::tuple<element_id::ElementId, Span<const uint8_t>>
ElementIterator::operator* () const {
const ElementHeader* header = FromBytes<ElementHeader>(remaining_);
ZX_ASSERT(header != nullptr);
return {
static_cast<element_id::ElementId>(header->id),
remaining_.subspan(sizeof(ElementHeader), header->len),
};
}
ElementIterator& ElementIterator::operator++() {
const ElementHeader* header = FromBytes<ElementHeader>(remaining_);
ZX_ASSERT(header != nullptr);
remaining_ = remaining_.subspan(sizeof(ElementHeader) + header->len);
SkipIfTooShort(&remaining_);
return *this;
}
static bool SpansHaveSameEnd(wlan::Span<const uint8_t> a, wlan::Span<const uint8_t> b) {
return a.data() + a.size() == b.data() + b.size();
}
bool operator== (const ElementIterator& a, const ElementIterator& b) {
// Comparing iterators from different containers is not legal
ZX_DEBUG_ASSERT(SpansHaveSameEnd(a.remaining_, b.remaining_));
return a.remaining_.data() == b.remaining_.data();
}
bool operator!= (const ElementIterator& a, const ElementIterator& b) {
return !(a == b);
}
} // common
} // wlan