grafton-visca-macros

Crates.iografton-visca-macros
lib.rsgrafton-visca-macros
version0.7.0
created_at2025-08-07 13:19:26.430665+00
updated_at2025-09-18 10:27:36.885694+00
descriptionProcedural macros for the grafton-visca library
homepagehttps://www.grafton.ai
repositoryhttps://github.com/GrantSparks/grafton-visca
max_upload_size
id1785267
size116,442
Grant Sparks (GrantSparks)

documentation

README

grafton-visca-macros

Crates.io Documentation License

Procedural macros for the grafton-visca crate, providing derive macros to eliminate boilerplate in VISCA protocol implementations.

Overview

This crate provides four macros that work together to create type-safe, efficient VISCA protocol implementations:

  • ViscaInquiry - Generate inquiry command implementations with parser support
  • ViscaEnum - Automatic enum/u8 conversions for protocol values
  • ViscaValue - Value wrapper types with VISCA encoding
  • delegate_to_session - Auto-generate CameraSession forwarding implementations

ViscaInquiry

Generates complete Command trait implementations for inquiry commands, including response parsing.

Basic Usage

use grafton_visca_macros::ViscaInquiry;

#[derive(ViscaInquiry, Debug, Copy, Clone)]
#[visca(command = 0x00, response = "Power", inquiry_variant = "Power", parser = "bool")]
pub struct PowerInquiry;

// For commands with subcategories:
#[derive(ViscaInquiry, Debug, Copy, Clone)]
#[visca(command = 0x12, sub_command = 0x06, response = "PanTiltPosition", inquiry_variant = "PanTiltPosition", parser = "pan_tilt")]
pub struct PanTiltPositionInquiry;

Generated Code

The macro generates:

  • Command trait implementation
  • to_bytes() method returning VISCA command bytes
  • response_kind() method returning expected ResponseType
  • command_category() method returning the category
  • parse_response() method when parser is specified
  • From conversion to the InquiryCommand enum

Parser Types

  • "bool" - Boolean values (0x02 = true, 0x03 = false)
  • "byte" - Direct byte value
  • "position" - 4-nibble position value (converts to u16)
  • "nibble" - Extended nibble encoding
  • "offset" - Byte value with offset subtraction
  • "flags" - Bit flags (for image flip)
  • "mode" - Enum value parsing
  • "pan_tilt" - Special parser for pan/tilt positions

ViscaEnum

Generates bidirectional u8 conversions for enums representing VISCA protocol values.

Basic Usage

use grafton_visca_macros::ViscaEnum;

#[derive(Debug, Copy, Clone, PartialEq, Eq, ViscaEnum)]
pub enum ExposureMode {
    Auto = 0x00,
    Manual = 0x03,
    Shutter = 0x0A,
    Iris = 0x0B,
    Bright = 0x0D,
}

Generated Implementations

  • TryFrom<u8> - Converts u8 to enum with validation
  • From<Enum> for u8 - Converts enum to u8 value
  • is_valid_discriminant(u8) -> bool - Const validation function

Advanced Features

#[derive(Debug, Copy, Clone, PartialEq, Eq, ViscaEnum)]
#[visca_enum(error_type = MyError, exhaustive = false)]
pub enum Mode {
    #[visca_enum(name = "Automatic Mode")]
    Auto = 0x00,

    #[visca_enum(name = "Manual Control")]
    Manual = 0x03,

    #[visca_enum(skip)]  // Excluded from TryFrom<u8>
    _Reserved = 0xFF,
}

ViscaValue

Creates value wrapper types with VISCA encoding and validation.

Basic Usage

use grafton_visca_macros::ViscaValue;

#[derive(ViscaValue, Debug, Copy, Clone)]
#[visca_value(bytes = 2)]
struct ZoomPosition(u16);

#[derive(ViscaValue, Debug, Copy, Clone)]
#[visca_value(bytes = 1)]
struct ZoomSpeed(u8);

Generated Methods

The macro generates methods for:

  • Converting to/from byte representations
  • Validation of value ranges
  • VISCA protocol encoding

delegate_to_session

Attribute macro for auto-generating CameraSession forwarding implementations.

Usage

use grafton_visca_macros::delegate_to_session;

#[delegate_to_session]
pub trait ZoomControl {
    type Mode: Mode;

    fn zoom_stop(&self) -> <Self::Mode as Mode>::Ret<'_, Result<(), Error>>;
    fn zoom_tele_std(&self) -> <Self::Mode as Mode>::Ret<'_, Result<(), Error>>;
    // ... more methods
}

The macro generates forwarding implementations that delegate from CameraSession to the inner Camera instance with proper error handling.

Integration with grafton-visca

These macros are re-exported by the main grafton-visca crate:

use grafton_visca::{ViscaInquiry, ViscaEnum, ViscaValue};
use grafton_visca::camera::delegate_to_session;

Benefits

  1. Type Safety - Each command and value is a distinct type
  2. Zero Boilerplate - Macros generate all repetitive code
  3. Protocol Safety - Automatic VISCA terminator handling
  4. Compile-time Validation - Invalid attributes caught at compile time
  5. Consistent API - All commands follow the same patterns
  6. Performance - Zero-cost abstractions with const functions where possible

Examples

Example Inquiry and Enum

use grafton_visca_macros::{ViscaInquiry, ViscaEnum};

#[derive(Debug, Copy, Clone, PartialEq, Eq, ViscaEnum)]
pub enum ExposureMode {
    Auto = 0x00,
    Manual = 0x03,
    Shutter = 0x0A,
    Iris = 0x0B,
}

#[derive(ViscaInquiry, Debug, Copy, Clone)]
#[visca(command = 0x39, response = "ExposureMode", inquiry_variant = "ExposureMode", parser = "mode")]
pub struct ExposureModeInquiry;

Value Types with Validation

use grafton_visca_macros::ViscaValue;

#[derive(ViscaValue, Debug, Copy, Clone)]
#[visca_value(bytes = 2, min = 0x0000, max = 0x4000)]
pub struct ZoomPosition(u16);

impl ZoomPosition {
    pub fn from_percentage(percent: f32) -> Result<Self, Error> {
        let value = (percent.clamp(0.0, 100.0) * 0x4000 as f32 / 100.0) as u16;
        Ok(Self(value))
    }

    pub fn to_percentage(&self) -> f32 {
        self.0 as f32 * 100.0 / 0x4000 as f32
    }
}

Requirements

  • Rust 1.80 or later
  • The response attribute in ViscaInquiry must reference existing ResponseType variants
  • The inquiry_variant attribute must reference existing InquiryCommand enum variants
  • Enums using ViscaEnum must have explicit discriminant values
  • All discriminant values must be unique and valid u8 values (0-255)

Version Compatibility

This crate follows the same versioning as the main grafton-visca crate. Always use matching versions:

[dependencies]
grafton-visca = "0.7"
grafton-visca-macros = "0.7"

License

Licensed under MIT OR Apache-2.0 dual license. See the LICENSE-MIT and LICENSE-APACHE files in the repository root.

Commit count: 893

cargo fmt