servicepoint_binding_c 0.15.0

C bindings for the servicepoint crate.
Documentation
use crate::{
    containers::ByteSlice,
    macros::{derive_clone, derive_free, wrap, wrap_functions},
};
use servicepoint::{CommandCode, Header, Packet};
use std::ptr::NonNull;

derive_clone!(Packet);
derive_free!(Packet);

wrap! {
    Packet {
    properties:
        prop header: Header { get; get mut; set; };
    functions:
        /// Tries to load a [Packet] from the passed array with the specified length.
        ///
        /// returns: NULL in case of an error, pointer to the allocated packet otherwise
        fn try_load(data: slice ByteSlice) -> move_ok *mut Packet {
            servicepoint::Packet::try_from(data)
        };

        /// Creates a raw [Packet] from parts.
        ///
        /// returns: new instance. Will never return null.
        fn from_parts(header: val Header, payload: val ByteSlice) -> move NonNull<Packet> {
            let payload = if payload == ByteSlice::INVALID {
                None
            } else {
                Some(Vec::from(unsafe { payload.as_slice() }))
            };

            Packet { header, payload }
        };
    methods:
        /// Returns a pointer to the current payload of the provided packet.
        ///
        /// Returns an [ByteSlice::INVALID] instance in case the packet does not have any payload.
        ///
        /// The returned memory can be changed and will be valid until a new payload is set.
        fn get_payload(mut packet) -> val ByteSlice {
            match &mut packet.payload {
                None => ByteSlice::INVALID,
                Some(payload) => unsafe { ByteSlice::from_slice(payload) },
            }
        };

        /// Sets the payload of the provided packet to the provided data.
        ///
        /// This makes previous payload pointers invalid.
        fn set_payload(mut packet, data: val ByteSlice) {
            packet.payload = if data == ByteSlice::INVALID {
                None
            } else {
                Some(unsafe { data.as_slice().to_vec() })
            }
        };

        /// Serialize the packet into the provided buffer.
        ///
        /// # Panics
        ///
        /// - if the buffer is not big enough to hold header+payload.
        fn serialize_to(mut packet, buffer: val ByteSlice) -> val usize {
            unsafe {
                packet.serialize_to(buffer.as_slice_mut()).unwrap_or(0)
            }
        };
    }
}

wrap_functions!(sp;
    /// Converts u16 into [CommandCode].
    ///
    /// If the provided value is not valid, false is returned and result is not changed.
    fn u16_to_command_code(code: val u16, result: mut NonNull<CommandCode>) -> val bool {
        match CommandCode::try_from(code) {
            Ok(code) => {
                *result = code;
                true
            }
            Err(_) => false,
        }
    };
);