| Crates.io | grafton-visca-macros |
| lib.rs | grafton-visca-macros |
| version | 0.7.0 |
| created_at | 2025-08-07 13:19:26.430665+00 |
| updated_at | 2025-09-18 10:27:36.885694+00 |
| description | Procedural macros for the grafton-visca library |
| homepage | https://www.grafton.ai |
| repository | https://github.com/GrantSparks/grafton-visca |
| max_upload_size | |
| id | 1785267 |
| size | 116,442 |
Procedural macros for the grafton-visca crate, providing derive macros to eliminate boilerplate in VISCA protocol implementations.
This crate provides four macros that work together to create type-safe, efficient VISCA protocol implementations:
ViscaInquiry - Generate inquiry command implementations with parser supportViscaEnum - Automatic enum/u8 conversions for protocol valuesViscaValue - Value wrapper types with VISCA encodingdelegate_to_session - Auto-generate CameraSession forwarding implementationsGenerates complete Command trait implementations for inquiry commands, including response parsing.
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;
The macro generates:
Command trait implementationto_bytes() method returning VISCA command bytesresponse_kind() method returning expected ResponseTypecommand_category() method returning the categoryparse_response() method when parser is specifiedFrom conversion to the InquiryCommand enum"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 positionsGenerates bidirectional u8 conversions for enums representing VISCA protocol values.
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,
}
TryFrom<u8> - Converts u8 to enum with validationFrom<Enum> for u8 - Converts enum to u8 valueis_valid_discriminant(u8) -> bool - Const validation function#[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,
}
Creates value wrapper types with VISCA encoding and validation.
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);
The macro generates methods for:
Attribute macro for auto-generating CameraSession forwarding implementations.
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.
These macros are re-exported by the main grafton-visca crate:
use grafton_visca::{ViscaInquiry, ViscaEnum, ViscaValue};
use grafton_visca::camera::delegate_to_session;
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;
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
}
}
response attribute in ViscaInquiry must reference existing ResponseType variantsinquiry_variant attribute must reference existing InquiryCommand enum variantsViscaEnum must have explicit discriminant valuesThis 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"
Licensed under MIT OR Apache-2.0 dual license. See the LICENSE-MIT and LICENSE-APACHE files in the repository root.