use bytes::{Buf, BufMut, Bytes};
use std::net::{Ipv4Addr, Ipv6Addr};
use crate::capability::{Afi, Safi};
use crate::constants::orf;
use crate::error::DecodeError;
use crate::nlri::{Ipv4Prefix, Ipv6Prefix, Prefix};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum OrfType {
AddressPrefix,
AddressPrefixLegacy,
Unknown(u8),
}
impl OrfType {
#[must_use]
pub fn from_u8(value: u8) -> Self {
match value {
orf::TYPE_ADDRESS_PREFIX => Self::AddressPrefix,
orf::TYPE_ADDRESS_PREFIX_LEGACY => Self::AddressPrefixLegacy,
other => Self::Unknown(other),
}
}
#[must_use]
pub fn as_u8(self) -> u8 {
match self {
Self::AddressPrefix => orf::TYPE_ADDRESS_PREFIX,
Self::AddressPrefixLegacy => orf::TYPE_ADDRESS_PREFIX_LEGACY,
Self::Unknown(value) => value,
}
}
#[must_use]
pub fn is_address_prefix(self) -> bool {
matches!(self, Self::AddressPrefix | Self::AddressPrefixLegacy)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum OrfSendReceive {
Receive,
Send,
Both,
Unknown(u8),
}
impl OrfSendReceive {
#[must_use]
pub fn from_u8(value: u8) -> Self {
match value {
orf::SEND_RECEIVE_RECEIVE => Self::Receive,
orf::SEND_RECEIVE_SEND => Self::Send,
orf::SEND_RECEIVE_BOTH => Self::Both,
other => Self::Unknown(other),
}
}
#[must_use]
pub fn as_u8(self) -> u8 {
match self {
Self::Receive => orf::SEND_RECEIVE_RECEIVE,
Self::Send => orf::SEND_RECEIVE_SEND,
Self::Both => orf::SEND_RECEIVE_BOTH,
Self::Unknown(value) => value,
}
}
#[must_use]
pub fn can_send(self) -> bool {
matches!(self, Self::Send | Self::Both)
}
#[must_use]
pub fn can_receive(self) -> bool {
matches!(self, Self::Receive | Self::Both)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct OrfCapType {
pub orf_type: OrfType,
pub send_receive: OrfSendReceive,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OrfCapEntry {
pub afi: Afi,
pub safi: Safi,
pub orf_types: Vec<OrfCapType>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum WhenToRefresh {
Immediate,
Defer,
Unknown(u8),
}
impl WhenToRefresh {
#[must_use]
pub fn from_u8(value: u8) -> Self {
match value {
orf::WHEN_IMMEDIATE => Self::Immediate,
orf::WHEN_DEFER => Self::Defer,
other => Self::Unknown(other),
}
}
#[must_use]
pub fn as_u8(self) -> u8 {
match self {
Self::Immediate => orf::WHEN_IMMEDIATE,
Self::Defer => orf::WHEN_DEFER,
Self::Unknown(value) => value,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum OrfAction {
Add,
Remove,
RemoveAll,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum OrfMatch {
Permit,
Deny,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AddressPrefixOrf {
pub action: OrfAction,
pub match_: OrfMatch,
pub sequence: u32,
pub min_len: u8,
pub max_len: u8,
pub prefix: Option<Prefix>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OrfEntries {
AddressPrefix(Vec<AddressPrefixOrf>),
Raw(Bytes),
Malformed(Bytes),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OrfEntryGroup {
pub orf_type: OrfType,
pub entries: OrfEntries,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OrfPayload {
pub when_to_refresh: WhenToRefresh,
pub groups: Vec<OrfEntryGroup>,
}
#[must_use]
pub fn capability_value_len(entries: &[OrfCapEntry]) -> usize {
entries.iter().map(|e| 5 + 2 * e.orf_types.len()).sum()
}
pub fn encode_capability_value(entries: &[OrfCapEntry], buf: &mut impl BufMut) {
for entry in entries {
buf.put_u16(entry.afi as u16);
buf.put_u8(0); buf.put_u8(entry.safi as u8);
let count = u8::try_from(entry.orf_types.len()).unwrap_or(u8::MAX);
buf.put_u8(count);
for t in &entry.orf_types {
buf.put_u8(t.orf_type.as_u8());
buf.put_u8(t.send_receive.as_u8());
}
}
}
#[must_use]
pub fn decode_capability_value(mut raw: &[u8]) -> Option<Vec<OrfCapEntry>> {
if raw.is_empty() {
return None;
}
let mut entries = Vec::new();
while !raw.is_empty() {
if raw.len() < 5 {
return None;
}
let afi_raw = u16::from_be_bytes([raw[0], raw[1]]);
let safi_raw = raw[3];
let count = usize::from(raw[4]);
raw = &raw[5..];
if raw.len() < count * 2 {
return None;
}
let afi = Afi::from_u16(afi_raw)?;
let safi = Safi::from_u8(safi_raw)?;
let mut orf_types = Vec::with_capacity(count);
for _ in 0..count {
orf_types.push(OrfCapType {
orf_type: OrfType::from_u8(raw[0]),
send_receive: OrfSendReceive::from_u8(raw[1]),
});
raw = &raw[2..];
}
entries.push(OrfCapEntry {
afi,
safi,
orf_types,
});
}
Some(entries)
}
pub fn decode_route_refresh_orf(
buf: &mut impl Buf,
family: Option<(Afi, Safi)>,
) -> Result<OrfPayload, DecodeError> {
if buf.remaining() < 1 {
return Err(DecodeError::Incomplete {
needed: 1,
available: buf.remaining(),
});
}
let when_to_refresh = WhenToRefresh::from_u8(buf.get_u8());
let mut groups = Vec::new();
while buf.remaining() > 0 {
if buf.remaining() < 3 {
return Err(DecodeError::Incomplete {
needed: 3,
available: buf.remaining(),
});
}
let orf_type = OrfType::from_u8(buf.get_u8());
let len = usize::from(buf.get_u16());
if buf.remaining() < len {
return Err(DecodeError::Incomplete {
needed: len,
available: buf.remaining(),
});
}
let group_bytes = buf.copy_to_bytes(len);
let parse_family = match family {
Some((afi @ (Afi::Ipv4 | Afi::Ipv6), Safi::Unicast))
if orf_type.is_address_prefix() =>
{
Some(afi)
}
_ => None,
};
let entries = if let Some(afi) = parse_family {
match decode_address_prefix_entries(&group_bytes, afi) {
Ok(parsed) => OrfEntries::AddressPrefix(parsed),
Err(_) => OrfEntries::Malformed(group_bytes),
}
} else {
OrfEntries::Raw(group_bytes)
};
groups.push(OrfEntryGroup { orf_type, entries });
}
Ok(OrfPayload {
when_to_refresh,
groups,
})
}
pub fn encode_route_refresh_orf(
payload: &OrfPayload,
buf: &mut impl BufMut,
) -> Result<(), crate::error::EncodeError> {
buf.put_u8(payload.when_to_refresh.as_u8());
for group in &payload.groups {
let mut group_buf = bytes::BytesMut::new();
match &group.entries {
OrfEntries::AddressPrefix(entries) => {
for entry in entries {
encode_address_prefix_entry(entry, &mut group_buf);
}
}
OrfEntries::Raw(raw) | OrfEntries::Malformed(raw) => group_buf.put_slice(raw),
}
let len = u16::try_from(group_buf.len()).map_err(|_| {
crate::error::EncodeError::ValueOutOfRange {
field: "orf_group_length",
value: group_buf.len().to_string(),
}
})?;
buf.put_u8(group.orf_type.as_u8());
buf.put_u16(len);
buf.put_slice(&group_buf);
}
Ok(())
}
#[must_use]
pub fn route_refresh_orf_len(payload: &OrfPayload) -> usize {
let mut len = 1;
for group in &payload.groups {
let entry_bytes = match &group.entries {
OrfEntries::AddressPrefix(entries) => {
entries.iter().map(address_prefix_entry_len).sum::<usize>()
}
OrfEntries::Raw(raw) | OrfEntries::Malformed(raw) => raw.len(),
};
len += 3 + entry_bytes;
}
len
}
fn address_prefix_entry_len(entry: &AddressPrefixOrf) -> usize {
match entry.action {
OrfAction::RemoveAll => 1,
OrfAction::Add | OrfAction::Remove => {
let prefix_bytes = entry
.prefix
.map_or(0, |p| usize::from(p.prefix_len().div_ceil(8)));
8 + prefix_bytes
}
}
}
fn decode_address_prefix_entries(
mut raw: &[u8],
family: Afi,
) -> Result<Vec<AddressPrefixOrf>, DecodeError> {
let mut entries = Vec::new();
while !raw.is_empty() {
let header = raw[0];
raw = &raw[1..];
let match_ = if header & orf::MATCH_MASK != 0 {
OrfMatch::Deny
} else {
OrfMatch::Permit
};
let action = match header & orf::ACTION_MASK {
orf::ACTION_ADD => OrfAction::Add,
orf::ACTION_REMOVE => OrfAction::Remove,
orf::ACTION_REMOVE_ALL => OrfAction::RemoveAll,
_ => {
return Err(DecodeError::InvalidNetworkField {
detail: format!("ORF entry has undefined Action in header {header:#x}"),
data: vec![header],
});
}
};
if action == OrfAction::RemoveAll {
entries.push(AddressPrefixOrf {
action,
match_,
sequence: 0,
min_len: 0,
max_len: 0,
prefix: None,
});
continue;
}
if raw.len() < 7 {
return Err(DecodeError::Incomplete {
needed: 7,
available: raw.len(),
});
}
let sequence = u32::from_be_bytes([raw[0], raw[1], raw[2], raw[3]]);
let min_len = raw[4];
let max_len = raw[5];
let prefix_len = raw[6];
raw = &raw[7..];
let prefix = decode_orf_prefix(&mut raw, family, prefix_len)?;
entries.push(AddressPrefixOrf {
action,
match_,
sequence,
min_len,
max_len,
prefix: Some(prefix),
});
}
Ok(entries)
}
fn decode_orf_prefix(raw: &mut &[u8], family: Afi, prefix_len: u8) -> Result<Prefix, DecodeError> {
let max_len = match family {
Afi::Ipv4 => 32,
Afi::Ipv6 => 128,
Afi::L2Vpn => unreachable!("Address-Prefix ORF parser is gated to IP unicast families"),
};
if prefix_len > max_len {
return Err(DecodeError::InvalidNetworkField {
detail: format!("ORF prefix length {prefix_len} exceeds {max_len}"),
data: vec![prefix_len],
});
}
let byte_count = usize::from(prefix_len.div_ceil(8));
if raw.len() < byte_count {
return Err(DecodeError::Incomplete {
needed: byte_count,
available: raw.len(),
});
}
let prefix = match family {
Afi::Ipv4 => {
let mut octets = [0u8; 4];
octets[..byte_count].copy_from_slice(&raw[..byte_count]);
Prefix::V4(Ipv4Prefix::new(Ipv4Addr::from(octets), prefix_len))
}
Afi::Ipv6 => {
let mut octets = [0u8; 16];
octets[..byte_count].copy_from_slice(&raw[..byte_count]);
Prefix::V6(Ipv6Prefix::new(Ipv6Addr::from(octets), prefix_len))
}
Afi::L2Vpn => unreachable!("Address-Prefix ORF parser is gated to IP unicast families"),
};
*raw = &raw[byte_count..];
Ok(prefix)
}
fn encode_address_prefix_entry(entry: &AddressPrefixOrf, buf: &mut impl BufMut) {
let action_bits = match entry.action {
OrfAction::Add => orf::ACTION_ADD,
OrfAction::Remove => orf::ACTION_REMOVE,
OrfAction::RemoveAll => orf::ACTION_REMOVE_ALL,
};
let match_bits = match entry.match_ {
OrfMatch::Permit => 0,
OrfMatch::Deny => orf::MATCH_DENY,
};
buf.put_u8(action_bits | match_bits);
if entry.action == OrfAction::RemoveAll {
return;
}
buf.put_u32(entry.sequence);
buf.put_u8(entry.min_len);
buf.put_u8(entry.max_len);
match entry.prefix {
Some(Prefix::V4(p)) => {
buf.put_u8(p.len);
let n = usize::from(p.len.div_ceil(8));
buf.put_slice(&p.addr.octets()[..n]);
}
Some(Prefix::V6(p)) => {
buf.put_u8(p.len);
let n = usize::from(p.len.div_ceil(8));
buf.put_slice(&p.addr.octets()[..n]);
}
None => buf.put_u8(0),
}
}
#[cfg(test)]
mod tests {
use super::*;
use bytes::BytesMut;
fn ap(
action: OrfAction,
match_: OrfMatch,
sequence: u32,
min_len: u8,
max_len: u8,
prefix: Option<Prefix>,
) -> AddressPrefixOrf {
AddressPrefixOrf {
action,
match_,
sequence,
min_len,
max_len,
prefix,
}
}
fn v4(addr: [u8; 4], len: u8) -> Prefix {
Prefix::V4(Ipv4Prefix::new(Ipv4Addr::from(addr), len))
}
#[test]
fn capability_value_roundtrip_receive() {
let entries = vec![
OrfCapEntry {
afi: Afi::Ipv4,
safi: Safi::Unicast,
orf_types: vec![OrfCapType {
orf_type: OrfType::AddressPrefix,
send_receive: OrfSendReceive::Receive,
}],
},
OrfCapEntry {
afi: Afi::Ipv6,
safi: Safi::Unicast,
orf_types: vec![
OrfCapType {
orf_type: OrfType::AddressPrefix,
send_receive: OrfSendReceive::Both,
},
OrfCapType {
orf_type: OrfType::AddressPrefixLegacy,
send_receive: OrfSendReceive::Send,
},
],
},
];
let mut buf = BytesMut::new();
encode_capability_value(&entries, &mut buf);
assert_eq!(buf.len(), capability_value_len(&entries));
let decoded = decode_capability_value(&buf).unwrap();
assert_eq!(decoded, entries);
}
#[test]
fn capability_value_unknown_type_preserved() {
let entries = vec![OrfCapEntry {
afi: Afi::Ipv4,
safi: Safi::Unicast,
orf_types: vec![OrfCapType {
orf_type: OrfType::Unknown(200),
send_receive: OrfSendReceive::Receive,
}],
}];
let mut buf = BytesMut::new();
encode_capability_value(&entries, &mut buf);
let decoded = decode_capability_value(&buf).unwrap();
assert_eq!(decoded, entries);
}
#[test]
fn capability_value_unknown_afi_rejected() {
let raw = [0u8, 99, 0, 1, 1, 64, 1];
assert!(decode_capability_value(&raw).is_none());
}
#[test]
fn capability_value_truncated_rejected() {
let raw = [0u8, 1, 0, 1]; assert!(decode_capability_value(&raw).is_none());
}
#[test]
fn rr_orf_roundtrip_add_permit_and_deny() {
let payload = OrfPayload {
when_to_refresh: WhenToRefresh::Immediate,
groups: vec![OrfEntryGroup {
orf_type: OrfType::AddressPrefix,
entries: OrfEntries::AddressPrefix(vec![
ap(
OrfAction::Add,
OrfMatch::Permit,
10,
24,
32,
Some(v4([10, 0, 0, 0], 8)),
),
ap(
OrfAction::Add,
OrfMatch::Deny,
20,
0,
0,
Some(v4([192, 168, 0, 0], 16)),
),
]),
}],
};
let mut buf = BytesMut::new();
encode_route_refresh_orf(&payload, &mut buf).unwrap();
assert_eq!(buf.len(), route_refresh_orf_len(&payload));
let mut cursor = buf.freeze();
let decoded =
decode_route_refresh_orf(&mut cursor, Some((Afi::Ipv4, Safi::Unicast))).unwrap();
assert_eq!(decoded, payload);
}
#[test]
fn rr_orf_roundtrip_remove_and_remove_all() {
let payload = OrfPayload {
when_to_refresh: WhenToRefresh::Defer,
groups: vec![OrfEntryGroup {
orf_type: OrfType::AddressPrefix,
entries: OrfEntries::AddressPrefix(vec![
ap(OrfAction::RemoveAll, OrfMatch::Permit, 0, 0, 0, None),
ap(
OrfAction::Remove,
OrfMatch::Permit,
5,
0,
0,
Some(v4([172, 16, 0, 0], 12)),
),
]),
}],
};
let mut buf = BytesMut::new();
encode_route_refresh_orf(&payload, &mut buf).unwrap();
let mut cursor = buf.freeze();
let decoded =
decode_route_refresh_orf(&mut cursor, Some((Afi::Ipv4, Safi::Unicast))).unwrap();
assert_eq!(decoded, payload);
}
#[test]
fn rr_orf_roundtrip_default_route_and_host_route() {
let payload = OrfPayload {
when_to_refresh: WhenToRefresh::Immediate,
groups: vec![OrfEntryGroup {
orf_type: OrfType::AddressPrefix,
entries: OrfEntries::AddressPrefix(vec![
ap(
OrfAction::Add,
OrfMatch::Permit,
1,
0,
0,
Some(v4([0, 0, 0, 0], 0)),
),
ap(
OrfAction::Add,
OrfMatch::Permit,
2,
0,
0,
Some(v4([10, 1, 2, 3], 32)),
),
]),
}],
};
let mut buf = BytesMut::new();
encode_route_refresh_orf(&payload, &mut buf).unwrap();
let mut cursor = buf.freeze();
let decoded =
decode_route_refresh_orf(&mut cursor, Some((Afi::Ipv4, Safi::Unicast))).unwrap();
assert_eq!(decoded, payload);
}
#[test]
fn rr_orf_roundtrip_ipv6_host_route() {
let p = Prefix::V6(Ipv6Prefix::new("2001:db8::1".parse().unwrap(), 128));
let payload = OrfPayload {
when_to_refresh: WhenToRefresh::Immediate,
groups: vec![OrfEntryGroup {
orf_type: OrfType::AddressPrefix,
entries: OrfEntries::AddressPrefix(vec![ap(
OrfAction::Add,
OrfMatch::Deny,
7,
64,
128,
Some(p),
)]),
}],
};
let mut buf = BytesMut::new();
encode_route_refresh_orf(&payload, &mut buf).unwrap();
let mut cursor = buf.freeze();
let decoded =
decode_route_refresh_orf(&mut cursor, Some((Afi::Ipv6, Safi::Unicast))).unwrap();
assert_eq!(decoded, payload);
}
#[test]
fn rr_orf_legacy_type_128_parsed() {
let payload = OrfPayload {
when_to_refresh: WhenToRefresh::Immediate,
groups: vec![OrfEntryGroup {
orf_type: OrfType::AddressPrefixLegacy,
entries: OrfEntries::AddressPrefix(vec![ap(
OrfAction::Add,
OrfMatch::Permit,
1,
0,
0,
Some(v4([10, 0, 0, 0], 8)),
)]),
}],
};
let mut buf = BytesMut::new();
encode_route_refresh_orf(&payload, &mut buf).unwrap();
let mut cursor = buf.freeze();
let decoded =
decode_route_refresh_orf(&mut cursor, Some((Afi::Ipv4, Safi::Unicast))).unwrap();
assert_eq!(decoded, payload);
}
#[test]
fn rr_orf_unknown_type_preserved_as_raw() {
let mut buf = BytesMut::new();
buf.put_u8(WhenToRefresh::Immediate.as_u8());
buf.put_u8(9); buf.put_u16(3);
buf.put_slice(&[0xAA, 0xBB, 0xCC]);
let mut cursor = buf.freeze();
let decoded =
decode_route_refresh_orf(&mut cursor, Some((Afi::Ipv4, Safi::Unicast))).unwrap();
assert_eq!(decoded.groups.len(), 1);
assert_eq!(decoded.groups[0].orf_type, OrfType::Unknown(9));
assert_eq!(
decoded.groups[0].entries,
OrfEntries::Raw(Bytes::from_static(&[0xAA, 0xBB, 0xCC]))
);
}
#[test]
fn rr_orf_address_prefix_without_family_preserved_as_raw() {
let mut buf = BytesMut::new();
buf.put_u8(WhenToRefresh::Immediate.as_u8());
buf.put_u8(OrfType::AddressPrefix.as_u8());
buf.put_u16(8);
buf.put_u8(orf::ACTION_ADD);
buf.put_u32(1);
buf.put_u8(0);
buf.put_u8(0);
buf.put_u8(40); let mut cursor = buf.freeze();
let decoded = decode_route_refresh_orf(&mut cursor, None).unwrap();
assert_eq!(
decoded.groups[0].entries,
OrfEntries::Raw(Bytes::from_static(&[orf::ACTION_ADD, 0, 0, 0, 1, 0, 0, 40]))
);
}
#[test]
fn rr_orf_address_prefix_non_ip_family_preserved_as_raw() {
let mut buf = BytesMut::new();
buf.put_u8(WhenToRefresh::Immediate.as_u8());
buf.put_u8(OrfType::AddressPrefix.as_u8());
buf.put_u16(8);
buf.put_u8(orf::ACTION_ADD);
buf.put_u32(1);
buf.put_u8(0);
buf.put_u8(0);
buf.put_u8(40);
let mut cursor = buf.freeze();
let decoded =
decode_route_refresh_orf(&mut cursor, Some((Afi::L2Vpn, Safi::Evpn))).unwrap();
assert_eq!(
decoded.groups[0].entries,
OrfEntries::Raw(Bytes::from_static(&[orf::ACTION_ADD, 0, 0, 0, 1, 0, 0, 40]))
);
}
#[test]
fn rr_orf_address_prefix_non_unicast_family_preserved_as_raw() {
let mut buf = BytesMut::new();
buf.put_u8(WhenToRefresh::Immediate.as_u8());
buf.put_u8(OrfType::AddressPrefix.as_u8());
buf.put_u16(8);
buf.put_u8(orf::ACTION_ADD);
buf.put_u32(1);
buf.put_u8(0);
buf.put_u8(0);
buf.put_u8(40);
let mut cursor = buf.freeze();
let decoded =
decode_route_refresh_orf(&mut cursor, Some((Afi::Ipv4, Safi::FlowSpec))).unwrap();
assert_eq!(
decoded.groups[0].entries,
OrfEntries::Raw(Bytes::from_static(&[orf::ACTION_ADD, 0, 0, 0, 1, 0, 0, 40]))
);
}
#[test]
fn rr_orf_prefix_len_over_family_max_is_malformed_not_error() {
let mut buf = BytesMut::new();
buf.put_u8(WhenToRefresh::Immediate.as_u8());
buf.put_u8(OrfType::AddressPrefix.as_u8());
buf.put_u16(8);
buf.put_u8(orf::ACTION_ADD);
buf.put_u32(1);
buf.put_u8(0);
buf.put_u8(0);
buf.put_u8(40); let mut cursor = buf.freeze();
let decoded =
decode_route_refresh_orf(&mut cursor, Some((Afi::Ipv4, Safi::Unicast))).unwrap();
assert!(matches!(
decoded.groups[0].entries,
OrfEntries::Malformed(_)
));
}
#[test]
fn rr_orf_undefined_action_is_malformed_not_error() {
let mut buf = BytesMut::new();
buf.put_u8(WhenToRefresh::Immediate.as_u8());
buf.put_u8(OrfType::AddressPrefix.as_u8());
buf.put_u16(1);
buf.put_u8(0x40); let mut cursor = buf.freeze();
let decoded =
decode_route_refresh_orf(&mut cursor, Some((Afi::Ipv4, Safi::Unicast))).unwrap();
assert!(matches!(
decoded.groups[0].entries,
OrfEntries::Malformed(_)
));
}
#[test]
fn rr_orf_truncated_group_rejected() {
let mut buf = BytesMut::new();
buf.put_u8(WhenToRefresh::Immediate.as_u8());
buf.put_u8(OrfType::AddressPrefix.as_u8());
buf.put_u16(20); let mut cursor = buf.freeze();
assert!(decode_route_refresh_orf(&mut cursor, Some((Afi::Ipv4, Safi::Unicast))).is_err());
}
}