servicepoint_binding_c 0.15.0

C bindings for the servicepoint crate.
Documentation
use crate::{containers::ByteSlice, macros::wrap};
use servicepoint::{
    Brightness, BrightnessGrid, BrightnessGridCommand, ByteGrid, DataRef, Grid,
    Origin, Packet,
};
use std::{mem::transmute, ptr::NonNull};

wrap! {
    BrightnessGrid {
    derives: crate::containers::derive_container, crate::containers::derive_grid[Brightness];
    functions:
        /// Creates a new [BrightnessGrid] with the specified dimensions.
        ///
        /// returns: [BrightnessGrid] initialized to 0.
        ///
        /// # Examples
        /// ```C
        /// UdpSocket *connection = sp_udp_open("127.0.0.1:2342");
        /// if (connection == NULL)
        ///     return 1;
        ///
        /// BrightnessGrid *grid = sp_brightness_grid_new(2, 2);
        /// sp_brightness_grid_set(grid, 0, 0, 0);
        /// sp_brightness_grid_set(grid, 1, 1, 10);
        ///
        /// TypedCommand *command = sp_command_char_brightness(grid);
        /// sp_udp_free(connection);
        /// ```
        fn new(width: val usize, height: val usize) -> move NonNull<BrightnessGrid> {
            BrightnessGrid::new(width, height)
        };

        /// Loads a [BrightnessGrid] with the specified dimensions from the provided data.
        ///
        /// Any out of range values will be set to [Brightness::MAX] or [Brightness::MIN].
        ///
        /// returns: new [BrightnessGrid] instance, or NULL in case of an error.
        fn load(
            width: val usize,
            height: val usize,
            data: slice ByteSlice,
        ) -> move_some *mut BrightnessGrid {
            ByteGrid::load(width, height, data)
                .map(move |grid| grid.map(Brightness::saturating_from))
        };

    methods:
        /// Creates a [BrightnessGridCommand] and immediately turns that into a [Packet].
        ///
        /// The provided [BrightnessGrid] gets consumed.
        ///
        /// Returns NULL in case of an error.
        fn try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet {
            Packet::try_from(BrightnessGridCommand {
                grid,
                origin: Origin::new(x, y),
            })
        };

        /// Gets an unsafe reference to the data of the instance.
        ///
        /// The returned memory is valid for the lifetime of the grid.
        fn data_ref_mut(mut instance) -> slice ByteSlice {
            //noinspection RsAssertEqual
            const _: () = assert!(size_of::<Brightness>() == 1);

            let br_slice = instance.data_ref_mut();
            unsafe {
                transmute::<&mut [Brightness], &mut [u8]>(br_slice)
            }
        };
    }
}