Skip to content

Commit

Permalink
Add support for parsing extension data trees
Browse files Browse the repository at this point in the history
Refactor existing code to share between parsing YANG trees (`Context`) and
extension trees (`SchemaExtInstance`).

Signed-off-by: Christian Hopps <[email protected]>
  • Loading branch information
choppsv1 committed Jan 1, 2025
1 parent 2834c96 commit 2dcddec
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 24 deletions.
125 changes: 103 additions & 22 deletions src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crate::error::{Error, Result};
use crate::iter::{
Ancestors, MetadataList, NodeIterable, Set, Siblings, Traverse,
};
use crate::schema::SchemaExtInstance;
use crate::schema::{DataValue, SchemaModule, SchemaNode, SchemaNodeKind};
use crate::utils::*;
use libyang3_sys as ffi;
Expand Down Expand Up @@ -404,6 +405,11 @@ pub trait Data<'a> {

// ===== impl DataTree =====

enum CtxOrExt<'a> {
C(&'a Context),
E(&'a SchemaExtInstance<'a>)
}

impl<'a> DataTree<'a> {
/// Create new empty data tree.
pub fn new(context: &'a Context) -> DataTree<'a> {
Expand Down Expand Up @@ -486,44 +492,91 @@ impl<'a> DataTree<'a> {
Ok(unsafe { DataTree::from_raw(context, rnode) })
}

/// Parse (and validate) input data as a YANG data tree.
pub fn parse_string(
context: &'a Context,
fn _parse_string(
ctx_or_ext: CtxOrExt<'a>,
data: impl AsRef<[u8]>,
format: DataFormat,
parser_options: DataParserFlags,
validation_options: DataValidationFlags,
) -> Result<DataTree<'a>> {
let mut rnode = std::ptr::null_mut();
let rnode_ptr = &mut rnode;
let context = match ctx_or_ext {
CtxOrExt::C(c) => c,
CtxOrExt::E(e) => e.context,
};

// Create input handler.
let cdata = CString::new(data.as_ref()).unwrap();
let mut ly_in = std::ptr::null_mut();
let ret =
unsafe { ffi::ly_in_new_memory(cdata.as_ptr() as _, &mut ly_in) };
if ret != ffi::LY_ERR::LY_SUCCESS {
return Err(Error::new(context));
}

let ret = unsafe {
ffi::lyd_parse_data_mem(
context.raw,
cdata.as_ptr() as _,
format as u32,
parser_options.bits(),
validation_options.bits(),
rnode_ptr,
)
match ctx_or_ext {
CtxOrExt::C(c) => ffi::lyd_parse_data(c.raw,
std::ptr::null_mut(),
ly_in,
format as u32,
parser_options.bits(),
validation_options.bits(),
rnode_ptr),
CtxOrExt::E(e) => ffi::lyd_parse_ext_data(e.raw,
std::ptr::null_mut(),
ly_in,
format as u32,
parser_options.bits(),
validation_options.bits(),
rnode_ptr)
}
};
unsafe { ffi::ly_in_free(ly_in, 0) };

if ret != ffi::LY_ERR::LY_SUCCESS {
return Err(Error::new(context));
}

Ok(unsafe { DataTree::from_raw(context, rnode) })
}

/// Parse YANG data into an operation data tree.
pub fn parse_op_string(

/// Parse (and validate) input data as a YANG data tree.
pub fn parse_string(
context: &'a Context,
data: impl AsRef<[u8]>,
format: DataFormat,
parser_options: DataParserFlags,
validation_options: DataValidationFlags,
) -> Result<DataTree<'a>> {
DataTree::_parse_string(CtxOrExt::C(context), data, format, parser_options, validation_options)
}

/// Parse input data as an extension data tree using the given schema extension.
pub fn parse_ext_string(
ext: &'a SchemaExtInstance<'a>,
data: impl AsRef<[u8]>,
format: DataFormat,
parser_options: DataParserFlags,
validation_options: DataValidationFlags,
) -> Result<DataTree<'a>> {
DataTree::_parse_string(CtxOrExt::E(ext), data, format, parser_options, validation_options)
}

fn _parse_op_string(
ctx_or_ext: CtxOrExt<'a>,
data: impl AsRef<[u8]>,
format: DataFormat,
op: DataOperation,
) -> Result<DataTree<'a>> {
let mut rnode = std::ptr::null_mut();
let rnode_ptr = &mut rnode;
let context = match ctx_or_ext {
CtxOrExt::C(c) => c,
CtxOrExt::E(e) => e.context,
};

// Create input handler.
let cdata = CString::new(data.as_ref()).unwrap();
Expand All @@ -535,15 +588,22 @@ impl<'a> DataTree<'a> {
}

let ret = unsafe {
ffi::lyd_parse_op(
context.raw,
std::ptr::null_mut(),
ly_in,
format as u32,
op as u32,
rnode_ptr,
std::ptr::null_mut(),
)
match ctx_or_ext {
CtxOrExt::C(c) => ffi::lyd_parse_op(c.raw,
std::ptr::null_mut(),
ly_in,
format as u32,
op as u32,
rnode_ptr,
std::ptr::null_mut()),
CtxOrExt::E(e) => ffi::lyd_parse_ext_op(e.raw,
std::ptr::null_mut(),
ly_in,
format as u32,
op as u32,
rnode_ptr,
std::ptr::null_mut())
}
};
unsafe { ffi::ly_in_free(ly_in, 0) };

Expand All @@ -554,6 +614,27 @@ impl<'a> DataTree<'a> {
Ok(unsafe { DataTree::from_raw(context, rnode) })
}

/// Parse YANG data into an operation data tree.
pub fn parse_op_string(
context: &'a Context,
data: impl AsRef<[u8]>,
format: DataFormat,
op: DataOperation,
) -> Result<DataTree<'a>> {
DataTree::_parse_op_string(CtxOrExt::C(context), data, format, op)
}

/// Parse op data as an extension data tree using the given schema extension.
/// Parse input data into an operation data tree.
pub fn parse_op_ext_string(
ext: &'a SchemaExtInstance<'a>,
data: impl AsRef<[u8]>,
format: DataFormat,
op: DataOperation,
) -> Result<DataTree<'a>> {
DataTree::_parse_op_string(CtxOrExt::E(ext), data, format, op)
}

/// Returns a reference to the fist top-level data node, unless the data
/// tree is empty.
pub fn reference(&self) -> Option<DataNodeRef<'_>> {
Expand Down
4 changes: 2 additions & 2 deletions src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ pub struct SchemaLeafType<'a> {
/// YANG extension instance.
#[derive(Clone, Debug)]
pub struct SchemaExtInstance<'a> {
context: &'a Context,
raw: *mut ffi::lysc_ext_instance,
pub(crate) context: &'a Context,
pub(crate) raw: *mut ffi::lysc_ext_instance,
}

/// YANG data value type.
Expand Down

0 comments on commit 2dcddec

Please sign in to comment.