blob: 597560c9c54272d060278172713cc47d43307a4f [file] [log] [blame]
// Copyright 2021 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.
use crate::prelude_internal::*;
use std::ops::Deref;
/// Functional equivalent of [`otsys::otOperationalDataset`](crate::otsys::otOperationalDataset).
#[derive(Default, Clone)]
#[repr(transparent)]
pub struct OperationalDataset(pub otOperationalDataset);
impl_ot_castable!(OperationalDataset, otOperationalDataset);
impl OperationalDataset {
/// Returns an empty operational dataset.
pub fn empty() -> OperationalDataset {
Self::default()
}
/// Returns true if this dataset is considered "complete"
pub fn is_complete(&self) -> bool {
self.get_active_timestamp().is_some()
&& self.get_network_name().is_some()
&& self.get_network_key().is_some()
&& self.get_extended_pan_id().is_some()
&& self.get_mesh_local_prefix().is_some()
&& self.get_pan_id().is_some()
&& self.get_channel().is_some()
&& self.get_pskc().is_some()
&& self.get_security_policy().is_some()
&& self.get_channel_mask().is_some()
}
/// Clears all of the fields in this dataset.
pub fn clear(&mut self) {
*self = Self::empty();
}
// TODO: Not clear what the OpenThread API is to accomplish this.
// pub fn to_tlvs(&self) -> OperationalDatasetTlvs {
// todo!()
// }
}
impl std::fmt::Debug for OperationalDataset {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("OperationalDataset");
if let Some(x) = self.get_network_name() {
ds.field("network_name", &x);
}
if let Some(x) = self.get_extended_pan_id() {
ds.field("xpanid", &x);
}
if let Some(x) = self.get_network_key() {
ds.field("network_key", &x);
}
if let Some(x) = self.get_mesh_local_prefix() {
ds.field("mesh_local_prefix", &x);
}
if let Some(x) = self.get_pan_id() {
ds.field("panid", &x);
}
if let Some(x) = self.get_channel() {
ds.field("channel", &x);
}
if let Some(x) = self.get_channel_mask() {
ds.field("channel_mask", &x);
}
if let Some(x) = self.get_pskc() {
ds.field("pskc", &x);
}
if let Some(x) = self.get_security_policy() {
ds.field("security_policy", &x);
}
if let Some(x) = self.get_delay() {
ds.field("delay", &x);
}
if let Some(x) = self.get_active_timestamp() {
ds.field("active_timestamp", &x);
}
if let Some(x) = self.get_pending_timestamp() {
ds.field("pending_timestamp", &x);
}
ds.finish()
}
}
impl OperationalDataset {
/// Returns the channel index, if present.
pub fn get_channel(&self) -> Option<ChannelIndex> {
self.0.mComponents.mIsChannelPresent().then(|| self.0.mChannel.try_into().unwrap())
}
/// Returns the channel mask, if present.
pub fn get_channel_mask(&self) -> Option<ChannelMask> {
self.0.mComponents.mIsChannelMaskPresent().then(|| self.0.mChannelMask.into())
}
/// Returns the delay, if present.
pub fn get_delay(&self) -> Option<u32> {
self.0.mComponents.mIsDelayPresent().then(|| self.0.mDelay)
}
/// Returns the extended PAN-ID, if present.
pub fn get_extended_pan_id(&self) -> Option<&ExtendedPanId> {
self.0
.mComponents
.mIsExtendedPanIdPresent()
.then(|| ExtendedPanId::ref_from_ot_ref(&self.0.mExtendedPanId))
}
/// Returns the network key, if present.
pub fn get_network_key(&self) -> Option<&NetworkKey> {
self.0
.mComponents
.mIsNetworkKeyPresent()
.then(|| NetworkKey::ref_from_ot_ref(&self.0.mNetworkKey))
}
/// Returns the network key, if present.
pub fn get_pskc(&self) -> Option<&Pskc> {
self.0.mComponents.mIsPskcPresent().then(|| Pskc::ref_from_ot_ref(&self.0.mPskc))
}
/// Returns the network name, if present.
pub fn get_network_name(&self) -> Option<&NetworkName> {
self.0
.mComponents
.mIsNetworkNamePresent()
.then(|| NetworkName::ref_from_ot_ref(&self.0.mNetworkName))
}
/// Returns the PAN-ID, if present.
pub fn get_pan_id(&self) -> Option<PanId> {
self.0.mComponents.mIsPanIdPresent().then(|| self.0.mPanId)
}
/// Returns the active timestamp, if present.
pub fn get_active_timestamp(&self) -> Option<Timestamp> {
self.0.mComponents.mIsActiveTimestampPresent().then(|| self.0.mActiveTimestamp.into())
}
/// Returns the pending timestamp, if present.
pub fn get_pending_timestamp(&self) -> Option<Timestamp> {
self.0.mComponents.mIsPendingTimestampPresent().then(|| self.0.mPendingTimestamp.into())
}
/// Returns the security policy, if present.
pub fn get_security_policy(&self) -> Option<&SecurityPolicy> {
self.0
.mComponents
.mIsSecurityPolicyPresent()
.then(|| SecurityPolicy::ref_from_ot_ref(&self.0.mSecurityPolicy))
}
/// Returns the mesh-local prefix, if present.
pub fn get_mesh_local_prefix(&self) -> Option<&MeshLocalPrefix> {
self.0
.mComponents
.mIsMeshLocalPrefixPresent()
.then(|| &self.0.mMeshLocalPrefix)
.map(Into::into)
}
}
impl OperationalDataset {
/// Sets or clears the channel index.
pub fn set_channel(&mut self, opt: Option<ChannelIndex>) {
if let Some(x) = opt {
self.0.mChannel = x.into();
self.0.mComponents.set_mIsChannelPresent(true);
} else {
self.0.mComponents.set_mIsChannelPresent(false);
}
}
/// Sets or clears the channel mask.
pub fn set_channel_mask(&mut self, opt: Option<ChannelMask>) {
if let Some(x) = opt {
self.0.mChannelMask = x.into();
self.0.mComponents.set_mIsChannelMaskPresent(true);
} else {
self.0.mComponents.set_mIsChannelMaskPresent(false);
}
}
/// Sets or clears the delay.
pub fn set_delay(&mut self, opt: Option<u32>) {
if let Some(x) = opt {
self.0.mDelay = x;
self.0.mComponents.set_mIsDelayPresent(true);
} else {
self.0.mComponents.set_mIsDelayPresent(false);
}
}
/// Sets or clears the extended PAN-ID.
pub fn set_extended_pan_id(&mut self, opt: Option<&ExtendedPanId>) {
if let Some(x) = opt {
self.0.mExtendedPanId = x.as_ot_ref().clone();
self.0.mComponents.set_mIsExtendedPanIdPresent(true);
} else {
self.0.mComponents.set_mIsExtendedPanIdPresent(false);
}
}
/// Sets or clears the network key.
pub fn set_network_key(&mut self, opt: Option<&NetworkKey>) {
if let Some(x) = opt {
self.0.mNetworkKey = x.as_ot_ref().clone();
self.0.mComponents.set_mIsNetworkKeyPresent(true);
} else {
self.0.mComponents.set_mIsNetworkKeyPresent(false);
}
}
/// Sets or clears the network name.
pub fn set_network_name(&mut self, opt: Option<&NetworkName>) {
if let Some(x) = opt {
self.0.mNetworkName = x.as_ot_ref().clone();
self.0.mComponents.set_mIsNetworkNamePresent(true);
} else {
self.0.mComponents.set_mIsNetworkNamePresent(false);
}
}
/// Sets or clears the PAN-ID.
pub fn set_pan_id(&mut self, opt: Option<PanId>) {
if let Some(x) = opt {
self.0.mPanId = x;
self.0.mComponents.set_mIsPanIdPresent(true);
} else {
self.0.mComponents.set_mIsPanIdPresent(false);
}
}
/// Sets or clears the active timestamp
pub fn set_active_timestamp(&mut self, opt: Option<Timestamp>) {
if let Some(x) = opt {
self.0.mActiveTimestamp = x.into();
self.0.mComponents.set_mIsActiveTimestampPresent(true);
} else {
self.0.mComponents.set_mIsActiveTimestampPresent(false);
}
}
/// Sets or clears the pending timestamp.
pub fn set_pending_timestamp(&mut self, opt: Option<Timestamp>) {
if let Some(x) = opt {
self.0.mPendingTimestamp = x.into();
self.0.mComponents.set_mIsPendingTimestampPresent(true);
} else {
self.0.mComponents.set_mIsPendingTimestampPresent(false);
}
}
/// Sets or clears the security policy.
pub fn set_security_policy(&mut self, opt: Option<SecurityPolicy>) {
if let Some(x) = opt {
self.0.mSecurityPolicy = x.as_ot_ref().clone();
self.0.mComponents.set_mIsSecurityPolicyPresent(true);
} else {
self.0.mComponents.set_mIsSecurityPolicyPresent(false);
}
}
/// Sets or clears the mesh-local prefix.
pub fn set_mesh_local_prefix(&mut self, opt: Option<&MeshLocalPrefix>) {
if let Some(x) = opt {
self.0.mMeshLocalPrefix = x.as_ot_ref().clone();
self.0.mComponents.set_mIsMeshLocalPrefixPresent(true);
} else {
self.0.mComponents.set_mIsMeshLocalPrefixPresent(false);
}
}
}
/// Functional equivalent of [`otsys::otOperationalDatasetTlvs`](crate::otsys::otOperationalDatasetTlvs).
#[derive(Debug, Default, Clone)]
#[repr(transparent)]
pub struct OperationalDatasetTlvs(pub otOperationalDatasetTlvs);
impl_ot_castable!(OperationalDatasetTlvs, otOperationalDatasetTlvs);
impl OperationalDatasetTlvs {
/// Tries to parse the TLVs into a dataset
/// Functional equivalent to `otDatasetParseTlvs`
pub fn try_to_dataset(&self) -> Result<OperationalDataset> {
let mut ret = OperationalDataset::default();
Error::from(unsafe { otDatasetParseTlvs(self.as_ot_ptr(), ret.as_ot_mut_ptr()) })
.into_result()?;
Ok(ret)
}
/// Tries to create a `OperationalDatasetTlvs` instance from the given byte slice.
pub fn try_from_slice(slice: &[u8]) -> Result<Self, ot::WrongSize> {
let mut ret = Self::default();
let len = slice.len();
if len > OT_OPERATIONAL_DATASET_MAX_LENGTH as usize {
return Err(ot::WrongSize);
}
ret.0.mLength = len.try_into().unwrap();
ret.0.mTlvs[0..len].clone_from_slice(slice);
Ok(ret)
}
/// Returns length of the TLVs in bytes. 0-16.
pub fn len(&self) -> usize {
self.0.mLength as usize
}
/// Returns the TLVs as a byte slice with no trailing zeros.
pub fn as_slice(&self) -> &[u8] {
&self.0.mTlvs[0..self.len()]
}
/// Creates a `Vec<u8>` from the raw bytes of the TLVs
pub fn to_vec(&self) -> Vec<u8> {
self.as_slice().to_vec()
}
}
impl Deref for OperationalDatasetTlvs {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<'a> TryFrom<&'a [u8]> for OperationalDatasetTlvs {
type Error = ot::WrongSize;
fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
OperationalDatasetTlvs::try_from_slice(value)
}
}
impl TryFrom<Vec<u8>> for OperationalDatasetTlvs {
type Error = ot::WrongSize;
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
OperationalDatasetTlvs::try_from_slice(&value)
}
}
impl From<OperationalDatasetTlvs> for Vec<u8> {
fn from(value: OperationalDatasetTlvs) -> Self {
value.to_vec()
}
}
impl TryFrom<OperationalDatasetTlvs> for OperationalDataset {
type Error = ot::Error;
fn try_from(value: OperationalDatasetTlvs) -> Result<Self, Self::Error> {
value.try_to_dataset()
}
}