Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ffi/dnp3-schema/src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,7 @@ fn build_octet_string(
.add("value", byte_it.clone(), "Point value")?
.doc("Octet String point")?
.end_fields()?
.add_full_initializer("init")?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The goal of making OctetString constructible is correct, but this implementation will not work as intended for FFI clients due to a couple of fundamental issues.

  1. FunctionReturnStruct is not user-constructible: The octet_string_struct is defined as a FunctionReturnStruct. This struct type is designed for values returned from Rust and is opaque to FFI clients, meaning they cannot construct it. To create a user-constructible struct, you should use UniversalStruct.

  2. Iterator as a constructor argument: The value field has the type byte_iterator. FFI clients (e.g., in C# or Java) cannot create and pass an iterator. They work with collections, like a byte array. The value field should be changed to use a CollectionHandle, such as the byte_collection already defined in this file.

To properly expose a constructible OctetString, a refactoring of build_octet_string is needed. Here is a suggested implementation:

fn build_octet_string(
    lib: &mut LibraryBuilder,
    byte_collection: &CollectionHandle,
) -> Result<
    (
        UniversalStructHandle,
        AbstractIteratorHandle,
        AbstractIteratorHandle,
    ),
    BindingError,
> {
    let byte_it = lib.define_iterator_with_lifetime("byte_iterator", Primitive::U8)?;

    let octet_string_struct_decl = lib.declare_universal_struct("octet_string")?;
    let octet_string_struct = lib
        .define_universal_struct(octet_string_struct_decl)?
        .add("index", Primitive::U16, "Point index")?
        .add("value", byte_collection.clone(), "Point value")?
        .doc("Octet String point")?
        .end_fields()?
        .add_full_initializer("init")?
        .build()?;

    let octet_string_iterator =
        lib.define_iterator_with_lifetime("octet_string_iterator", octet_string_struct.clone())?;

    Ok((octet_string_struct, octet_string_iterator, byte_it))
}

Please note that this change will require further adjustments:

  • The define() function will need to be modified to pass byte_collection.
  • The SharedDefinitions struct will need to be updated to use UniversalStructHandle for _octet_string.

I'm providing this broader context here as I'm limited to commenting on the changed lines.

.build()?;

let octet_string_iterator =
Expand Down