diff --git a/src/schema.rs b/src/schema.rs index cef2a5e..94e21f7 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -109,6 +109,13 @@ pub struct SchemaStmtWhen<'a> { _marker: std::marker::PhantomData<&'a Context>, } +/// YANG leaf(-list) type. +#[derive(Clone, Debug)] +pub struct SchemaLeafType<'a> { + context: &'a Context, + raw: *mut ffi::lysc_type, +} + /// YANG data value type. #[derive(Copy, Clone, Debug, PartialEq, FromPrimitive)] pub enum DataValueType { @@ -651,26 +658,9 @@ impl<'a> SchemaNode<'a> { // TODO: list of leaf-list default values. - /// Resolved base type. - pub fn base_type(&self) -> Option { - let ltype = unsafe { - match self.kind() { - SchemaNodeKind::Leaf => { - (*(self.raw as *mut ffi::lysc_node_leaf)).type_ - } - SchemaNodeKind::LeafList => { - (*(self.raw as *mut ffi::lysc_node_leaflist)).type_ - } - _ => return None, - } - }; - let ltype = unsafe { (*ltype).basetype }; - Some(DataValueType::from_u32(ltype).unwrap()) - } - - /// Referenced typedef name of the leaf(-list). - pub fn typedef_name(&self) -> Option { - let ltype = unsafe { + /// Type of the leaf(-list) node. + pub fn leaf_type(&self) -> Option> { + let raw = unsafe { match self.kind() { SchemaNodeKind::Leaf => { (*(self.raw as *mut ffi::lysc_node_leaf)).type_ @@ -681,8 +671,8 @@ impl<'a> SchemaNode<'a> { _ => return None, } }; - let ltypedef = unsafe { (*ltype).name }; - char_ptr_to_opt_string(ltypedef) + let ltype = unsafe { SchemaLeafType::from_raw(self.context, raw) }; + Some(ltype) } /// Units of the leaf(-list)'s type. @@ -1037,6 +1027,51 @@ unsafe impl<'a> Binding<'a> for SchemaStmtWhen<'a> { unsafe impl Send for SchemaStmtWhen<'_> {} unsafe impl Sync for SchemaStmtWhen<'_> {} +// ===== impl SchemaLeafType ===== + +impl<'a> SchemaLeafType<'a> { + /// Returns the resolved base type. + pub fn base_type(&self) -> DataValueType { + let base_type = unsafe { (*self.raw).basetype }; + DataValueType::from_u32(base_type).unwrap() + } + + /// Returns the typedef name if it exists. + pub fn typedef_name(&self) -> Option { + let typedef = unsafe { (*self.raw).name }; + char_ptr_to_opt_string(typedef) + } + + /// Returns the real type of the leafref, corresponding to the first + /// non-leafref in a possible chain of leafrefs. + pub fn leafref_real_type(&self) -> Option> { + if self.base_type() != DataValueType::LeafRef { + return None; + } + + let leafref = self.raw as *mut ffi::lysc_type_leafref; + let real_type = unsafe { (*leafref).realtype }; + let ltype = + unsafe { SchemaLeafType::from_raw(self.context, real_type) }; + Some(ltype) + } +} + +unsafe impl<'a> Binding<'a> for SchemaLeafType<'a> { + type CType = ffi::lysc_type; + type Container = Context; + + unsafe fn from_raw( + context: &'a Context, + raw: *mut ffi::lysc_type, + ) -> SchemaLeafType<'_> { + SchemaLeafType { context, raw } + } +} + +unsafe impl Send for SchemaLeafType<'_> {} +unsafe impl Sync for SchemaLeafType<'_> {} + // ===== impl DataValue ===== impl DataValue { diff --git a/tests/schema.rs b/tests/schema.rs index 4c26b81..55e15bc 100644 --- a/tests/schema.rs +++ b/tests/schema.rs @@ -279,7 +279,7 @@ fn schema_node_attributes() { assert_eq!(snode.is_mandatory(), false); assert_eq!(snode.default_value_canonical(), Some("true")); assert_eq!(snode.default_value(), Some(DataValue::Bool(true))); - assert_eq!(snode.base_type(), Some(DataValueType::Bool)); + assert_eq!(snode.leaf_type().unwrap().base_type(), DataValueType::Bool); assert!(snode.units().is_none()); assert!(snode.musts().unwrap().count() == 0); assert!(snode.whens().count() == 0);