#[derive(Clone, Copy, Debug)]
pub struct FieldNames {
declared: &'static [&'static str],
forbidden: &'static [&'static str],
flattened: &'static [&'static FieldNames],
rejects_unknown: bool,
}
impl FieldNames {
#[doc(hidden)]
pub const fn new(
declared: &'static [&'static str],
forbidden: &'static [&'static str],
flattened: &'static [&'static FieldNames],
rejects_unknown: bool,
) -> Self {
Self {
declared,
forbidden,
flattened,
rejects_unknown,
}
}
pub const fn count(&self) -> usize {
let mut count = self.declared.len();
let mut section = 0;
while section < self.flattened.len() {
count += self.flattened[section].count();
section += 1;
}
count
}
pub const fn declaration(&self, name: &str) -> Option<usize> {
let mut index = 0;
while index < self.declared.len() {
if equal(self.declared[index], name) {
return Some(index);
}
index += 1;
}
let mut offset = self.declared.len();
let mut section = 0;
while section < self.flattened.len() {
if let Some(index) = self.flattened[section].declaration(name) {
return Some(offset + index);
}
offset += self.flattened[section].count();
section += 1;
}
None
}
pub const fn forbids(&self, name: &str) -> bool {
if contains(self.forbidden, name) {
return true;
}
let mut section = 0;
while section < self.flattened.len() {
if self.flattened[section].forbids(name) {
return true;
}
section += 1;
}
false
}
pub const fn rejects_unknown(&self) -> bool {
if self.rejects_unknown {
return true;
}
let mut section = 0;
while section < self.flattened.len() {
if self.flattened[section].rejects_unknown() {
return true;
}
section += 1;
}
false
}
#[doc(hidden)]
pub const fn names(&self, name: &str) -> bool {
self.declaration(name).is_some() || self.forbids(name)
}
#[doc(hidden)]
pub const fn shares_names_with(&self, other: &FieldNames) -> bool {
let mut index = 0;
while index < self.declared.len() {
if other.names(self.declared[index]) {
return true;
}
index += 1;
}
let mut index = 0;
while index < self.forbidden.len() {
if other.names(self.forbidden[index]) {
return true;
}
index += 1;
}
let mut section = 0;
while section < self.flattened.len() {
if self.flattened[section].shares_names_with(other) {
return true;
}
section += 1;
}
false
}
}
const fn contains(names: &[&str], name: &str) -> bool {
let mut index = 0;
while index < names.len() {
if equal(names[index], name) {
return true;
}
index += 1;
}
false
}
const fn equal(left: &str, right: &str) -> bool {
let (left, right) = (left.as_bytes(), right.as_bytes());
if left.len() != right.len() {
return false;
}
let mut index = 0;
while index < left.len() {
if left[index] != right[index] {
return false;
}
index += 1;
}
true
}